批量更新,删除,插入无法正常使用版本控制

时间:2012-01-03 07:33:29

标签: nhibernate fluent-nhibernate

我正在使用Nhibernate 3.2和流畅的nhibernate,我有两个表Customer Group和Customer,我使用TimeStamp Column进行锁管理版本控制。 我有这些类的以下类和映射:

public class Customer
{
    public Customer()
    {
    }
    public virtual int CustomerID { get; set; }
    public virtual CustomerGroup customerGroup { get; set; }
    public virtual int CustomerGroupID { get; set; }
    public virtual string CustomerRef { get; set; }
    public virtual string NameE { get; set; }
    public virtual string NameA { get; set; }
    public virtual byte[] TimeStamp { get; set; }
}

和他的地图

 public class CustomerMap : ClassMap<Customer> {

    public CustomerMap() {
        Table("Customer");
        Id(x => x.CustomerID).GeneratedBy.Identity().Column("CustomerID");
        Version(x =>x.TimeStamp).CustomType("BinaryBlob").Generated.Always().Column("TimeStamp");
        DynamicUpdate();
        OptimisticLock.Version();
        References(x =>x.customerGroup).Column("CustomerGroupID").ForeignKey("CustomerGroupID");
        Map(x => x.CustomerRef).Column("CustomerRef").Length(30).Unique();
        Map(x => x.NameE).Column("NameE").Not.Nullable().Length(100).Unique();
        Map(x => x.NameA).Column("NameA").Length(100);

和客户群:

 public class CustomerGroup {
    public CustomerGroup() {
       Customers = new List<Customer>(3);
     }
    public virtual int CustomerGroupID { get; set; }
    public virtual IList<Customer> Customers { get; set; }
    public virtual byte[] TimeStamp { get; set; }
   }

和他的地图:

 public CustomerGroupMap() {
        Table("CustomerGroup");
        Version(x => x.TimeStamp).CustomType("BinaryBlob").Generated.Always().Column("TimeStamp");
        DynamicUpdate();
        OptimisticLock.Version();
        Id(x => x.CustomerGroupID).GeneratedBy.Identity().Column("CustomerGroupID");
        HasMany(x => x.Customers).KeyColumn("CustomerGroupID");
  }

当我在属于特定客户群的客户列表中创建更新时,如下所示:

        ISession Session = OpenSession();
        Session.BeginTransaction();
        var customerGroupInfo = Session.Query<CustomerGroup>().Fetch(x => x.Customers).Single<CustomerGroup>(x => x.CustomerGroupID == 98);
        foreach (var item in customerGroupInfo.Customers)
        {
            item.NameE = "abc";
            Session.Update(item);
        }
        Session.Transaction.Commit();

应用这些sql语句:

UPDATE Customer SET    NameE = 'abc' 
WHERE  CustomerID = 200 AND TimeStamp = 0x00000000000092EF  

SELECT customer_.TimeStamp as TimeStamp1_ FROM   Customer customer_
WHERE  customer_.CustomerID = 200 

UPDATE Customer SET    NameE = 'abc'
WHERE  CustomerID = 201 AND TimeStamp = 0x00000000000092F0 

SELECT customer_.TimeStamp as TimeStamp1_ FROM   Customer customer_
WHERE  customer_.CustomerID = 201

。 。

每次更新和每次选择都在单程往返中运行。 我在配置中设置了属性adonet.batch_size属性,如下所示:

<property name="adonet.batch_size">20</property>

我在this post中读到了默认情况下在Nhibernate 3.2中创建的这种行为。 任何使批处理正常工作的技巧?

1 个答案:

答案 0 :(得分:2)

您可能会考虑将Session.FlushMode更改为自动以外的其他内容。这样,你可以这样做:

Session.FlushMode = NHibernate.FlushMode.Never
foreach (var item in customerGroupInfo.Customers)
{
    item.NameE = "abc";
    Session.Update(item);
}
Session.Flush();
Session.Transaction.Commit();
// Perhaps changing the flushmode after commit?
Session.FlushMode = NHibernate.FlushMode.Auto;

修改:

没关系,请参阅文档摘录:http://nhibernate.info/doc/nh/en/index.html#batch

似乎批处理与乐观锁定不相符合。

  

NHibernate支持批处理SQL更新命令(INSERT,UPDATE,DELETE),但有以下限制:

.NET Framework 2.0 or above is required,

**the Nhibernate's drive used for your RDBMS may not supports batching,**

since the implementation uses reflection to access members and types in System.Data assembly which are not normally visible, it may not function in environments where necessary permissions are not granted

**optimistic concurrency checking may be impaired since ADO.NET 2.0 does not return the number of rows affected by each statement in the batch, only the total number of rows affected by the batch.**