01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制
2014-05-28 14:31
375 查看
Nhibernate 并发控制
【1】悲观并发控制
正在使用数据的操作,加上锁,使用完后解锁释放资源。
使用场景:数据竞争激烈,锁的成本低于回滚事务的成本
缺点:阻塞,可能死锁
【2】乐观并发控制:
所谓乐观,就是乐观的认为其他人没有在用该资源,资源的使用者不加锁。
A 读取数据后,如果该数据被别人B修改,产生错误,A回滚事务并重新开始。
使用场景:数据竞争不激烈,回滚事务的成本低于锁的成本。
-----------------------------------------------------------------------------------------------------------
Nhibernate 支持乐观并发控制:
通过使用<version>或<timestamp>,节点配置。
注意: <version>要配置一定在<Id>节点之后。否则抛出配置错误。如下所示:
Customer.hbm.xmml
Order.hbm.xml
-------------------------------------------------------------------
使用<version>标签 配置,实现并发控制。
原理:检查数据库的Version字段的版本值:插入前检查本身携带的Version是否等于现在数据库的Version值,如果
【1】相等,插入成功,并且Vesion加保存带数据库。
【2】不相等,插入失败,并且抛出NHibernate.StaleObjectStateException类型异常,抛异常:所以并不需要Nhibernate事务的支持,用来回滚事务,因为根本就没插入。
-------------------------------------更新(Update)并发测试------------------------------------------
Customer更新(Update)并发测试:
Order更新(Update)并发测试:
注意:
注意已经把已经事务的相关代码注释掉了是为说明上面的并发控制并不需要事务的支持。Upadate的代码如下:
-------------------------------------删除(Update)并发测试------------------------------------------
如果启用了并发(即配置中添加了<version>标签属性),
那么删除的时候产生的SQL的Where语句会额外添加一个判断条件
where customer.Version = 数据库里.vesesion
测试代码:
单元测试结果如下图所示:
并发删除同一条记录,抛出NHibernate.StaleObjectStateException 类型的异常。
故测试通过。
【1】悲观并发控制
正在使用数据的操作,加上锁,使用完后解锁释放资源。
使用场景:数据竞争激烈,锁的成本低于回滚事务的成本
缺点:阻塞,可能死锁
【2】乐观并发控制:
所谓乐观,就是乐观的认为其他人没有在用该资源,资源的使用者不加锁。
A 读取数据后,如果该数据被别人B修改,产生错误,A回滚事务并重新开始。
使用场景:数据竞争不激烈,回滚事务的成本低于锁的成本。
-----------------------------------------------------------------------------------------------------------
Nhibernate 支持乐观并发控制:
通过使用<version>或<timestamp>,节点配置。
注意: <version>要配置一定在<Id>节点之后。否则抛出配置错误。如下所示:
Customer.hbm.xmml
<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"/> ......
Order.hbm.xml
<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"/>
-------------------------------------------------------------------
使用<version>标签 配置,实现并发控制。
原理:检查数据库的Version字段的版本值:插入前检查本身携带的Version是否等于现在数据库的Version值,如果
【1】相等,插入成功,并且Vesion加保存带数据库。
【2】不相等,插入失败,并且抛出NHibernate.StaleObjectStateException类型异常,抛异常:所以并不需要Nhibernate事务的支持,用来回滚事务,因为根本就没插入。
-------------------------------------更新(Update)并发测试------------------------------------------
Customer更新(Update)并发测试:
[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,更新失败。
}
Order更新(Update)并发测试:
[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,更新失败。
}
注意:
注意已经把已经事务的相关代码注释掉了是为说明上面的并发控制并不需要事务的支持。Upadate的代码如下:
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(); } }
-------------------------------------删除(Update)并发测试------------------------------------------
如果启用了并发(即配置中添加了<version>标签属性),
那么删除的时候产生的SQL的Where语句会额外添加一个判断条件
where customer.Version = 数据库里.vesesion
测试代码:
[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); }
单元测试结果如下图所示:
并发删除同一条记录,抛出NHibernate.StaleObjectStateException 类型的异常。
故测试通过。
相关文章推荐
- 01-04-01【Nhibernate (版本3.3.1.4000) 出入江湖】原生的SQL查询
- 01-05-01-2【Nhibernate (版本3.3.1.4000) 出入江湖】立即加载实现--NHibernateUtil.Initialize()和添加fetch关键字的HQL查询
- 01-04-02【Nhibernate (版本3.3.1.4000) 出入江湖】HQL查询
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存
- 01-04-03【Nhibernate (版本3.3.1.4000) 出入江湖】Criteria API关联查询
- 01-03-02-1【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作--cascade 级联相关
- 01-08-05【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate二级缓存:第三方MemCache缓存
- 01-01-01【Nhibernate (版本3.3.1.4000) 出入江湖】配置文件
- 01-06-01【Nhibernate (版本3.3.1.4000) 出入江湖】事务
- 01-03-02-2【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作-Save方法的一些问题
- 01-03-01【Nhibernate (版本3.3.1.4000) 出入江湖】id标签的unsaved-value属性
- 01-03-03【Nhibernate (版本3.3.1.4000) 出入江湖】cascade的测试
- 01-08-02【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider
- 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之查询缓存
- 01-08-04【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之命名缓存
- 01-05-01-1【Nhibernate (版本3.3.1.4000) 出入江湖】延迟加载及其class和集合(set、bag等)的Lazy属性配置组合对Get和Load方法的影响
- 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之缓存管理
- NHibernate考察系列 01 基础环境
- 07 PB12.5版本的WEBSERVICE部署指南