码迷,mamicode.com
首页 > 系统相关 > 详细

01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制

时间:2014-05-30 05:44:34      阅读:301      评论:0      收藏:0      [点我收藏+]

标签:c   style   class   blog   code   java   

Nhibernate 并发控制

【1】悲观并发控制

       正在使用数据的操作,加上锁,使用完后解锁释放资源。

使用场景:数据竞争激烈,锁的成本低于回滚事务的成本

缺点:阻塞,可能死锁

【2】乐观并发控制:

       所谓乐观,就是乐观的认为其他人没有在用该资源,资源的使用者不加锁。

      A 读取数据后,如果该数据被别人B修改,产生错误,A回滚事务并重新开始。

使用场景:数据竞争不激烈,回滚事务的成本低于锁的成本。

 

-----------------------------------------------------------------------------------------------------------

Nhibernate 支持乐观并发控制:

  通过使用<version>或<timestamp>,节点配置。

  注意: <version>要配置一定在<Id>节点之后。否则抛出配置错误。如下所示:

Customer.hbm.xmml

bubuko.com,布布扣
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                   namespace="Model" 
                   assembly="Model" 
                    default-lazy="true">
  
  <class name="Model.Customer, Model"
         table="Customer"
         discriminator-value="0" lazy="false">
    <!--unsaved-value="0" 主键表中不需要定义,而是需要在子表中定义-->
    <id name="CustomerId"
        column="CustomerId"
        type="int" 
        unsaved-value="0">
      <generator class="native" />
      <!-- unsaved-value used to be null and generator was increment in h2.0.3 -->
    </id>

    <!--version标签必须放在Id后面,否则出错-->
    <version name="Version"/>
......
bubuko.com,布布扣

 

Order.hbm.xml

bubuko.com,布布扣
  <class name="Model.Order, Model" 
         table ="[Order]"
         discriminator-value="0" lazy="true">
    <id name="OrderId"
        column="OrderId"
        type="int" 
        unsaved-value="0">
 <!--     unsaved-value="0">-->
      <generator class="native" />
      <!-- unsaved-value used to be null and generator was increment in h2.0.3 -->
    </id>
    
    <!--version标签必须放在Id后面,否则出错-->
    <version name="Version"/>
bubuko.com,布布扣

-------------------------------------------------------------------

 

使用<version>标签 配置,实现并发控制。

   原理:检查数据库的Version字段的版本值:插入前检查本身携带的Version是否等于现在数据库的Version值,如果

    【1】相等,插入成功,并且Vesion加保存带数据库。

    【2】不相等,插入失败,并且抛出NHibernate.StaleObjectStateException类型异常,抛异常:所以并不需要Nhibernate事务的支持,用来回滚事务,因为根本就没插入。

                    

 

   -------------------------------------更新(Update)并发测试------------------------------------------

 

Customer更新(Update)并发测试:

 

bubuko.com,布布扣
       [TestMethod]
       [ExpectedException(typeof(NHibernate.StaleObjectStateException))]
       public void TestVessionByUpdate()
       {
           CustomerService customerService = new CustomerService();
           OrderService orderService = new OrderService();

           Customer customer = new Customer()
           {
               FirstName = "Test",
               LastName = "TestVessionByUpdate",
               Age = 10
           };
           customerService.Add(customer);

           Customer customer1 = customerService.Get(customer.CustomerId);
           Customer customer2 = customerService.Get(customer.CustomerId);

           string customer1Name = "customer1";
           customer1.FirstName = customer1Name;
           customer2.FirstName = "customer2Test";

           customerService.Update(customer2);  //能保存到数据库,Customer的version加1
           customerService.Update(customer1);  //抛出异常NHibernate.StaleObjectStateException,更新失败。
 }

bubuko.com,布布扣

 

Order更新(Update)并发测试:

bubuko.com,布布扣
       [TestMethod]
       [ExpectedException(typeof(NHibernate.StaleObjectStateException))]
       public void TestVessionOrderByUpdateCustomer()
       {
           CustomerService customerService = new CustomerService();
           OrderService orderService = new OrderService();

           Customer customer = new Customer()
           {
               FirstName = "Test",
               LastName = "TestVessionOrderByUpdateCustomer",
               Age = 10
           };
           Order order1 = new Order()
           {
               OrderDate = DateTime.Now.AddMinutes(1),
               Customer = customer
           };

           customer.Orders.Add(order1);
           customerService.Add(customer);

           Customer customer1 = customerService.Get(customer.CustomerId);
           Customer customer2 = customerService.Get(customer.CustomerId);

           customer1.Orders.First<Order>().OrderDate = customer1.Orders.First<Order>().OrderDate.AddDays(1);
           customer2.Orders.First<Order>().OrderDate = customer2.Orders.First<Order>().OrderDate.AddYears(1);
           customerService.Update(customer2);  //Customer和Order都能保存到数据库,Order的version加1
           customerService.Update(customer1);  //抛出异常NHibernate.StaleObjectStateException,更新失败。
}
bubuko.com,布布扣

 

 注意:

        注意已经把已经事务的相关代码注释掉了是为说明上面的并发控制并不需要事务的支持。Upadate的代码如下:

bubuko.com,布布扣
        public void Update(Customer customer)
        {
            ISession session = _sessionManager.GetSession();
            //ITransaction transaction = session.BeginTransaction();

            try
            {
                session.Update(customer);
                session.Flush();
                //transaction.Commit();
            }
            catch (Exception)
            {
                //transaction.Rollback();
                throw;
            }
            finally
            {
                session.Close();
            }
        }
bubuko.com,布布扣

 

    -------------------------------------删除(Update)并发测试------------------------------------------

如果启用了并发(即配置中添加了<version>标签属性),

那么删除的时候产生的SQL的Where语句会额外添加一个判断条件

           where customer.Version = 数据库里.vesesion

 

测试代码:

bubuko.com,布布扣
       [TestMethod]
       [ExpectedException(typeof(NHibernate.StaleObjectStateException))]
       public void TestVessionDeleteCustomer()
       {
           CustomerService customerService = new CustomerService();
           OrderService orderService = new OrderService();

           Customer customer = new Customer()
           {
               FirstName = "Test",
               LastName = "TestVessionDeleteCustomer",
               Age = 10
           };
           customerService.Add(customer);
           Assert.IsNotNull(customerService.Get(customer.CustomerId));


           Customer customer1 = customerService.Get(customer.CustomerId);
           Customer customer2 = customerService.Get(customer.CustomerId);

           customerService.Delete(customer1);
           customerService.Delete(customer2);

       }
bubuko.com,布布扣

 

如下图所示:

bubuko.com,布布扣

 

 

如果并发删除同一条记录,会抛出NHibernate.StaleObjectStateException 类型的异常。

 

 

 

01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制,布布扣,bubuko.com

01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制

标签:c   style   class   blog   code   java   

原文地址:http://www.cnblogs.com/easy5weikai/p/3757052.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!