Nhibernate concurrency control
"1" Pessimistic concurrency control
The operation that is using the data, plus the lock, unlocks the resource when it is finished.
Usage Scenario: Data is highly competitive and the cost of locking is lower than the cost of rolling back the transaction
Cons: Blocking, possibly deadlock
"2" Optimistic concurrency control:
The so-called optimism is optimistic that other people are not using the resource, resource users are not locked.
A after reading the data, if the data is modified by someone else B, resulting in an error, a rolls back the transaction and begins again.
Usage Scenario: Data is less competitive and the cost of rolling back a transaction is lower than the cost of the lock.
-----------------------------------------------------------------------------------------------------------
Nhibernate supports optimistic concurrency control:
Node configuration by using <version> or <TIMESTAMP>
Note: <version> must be configured after the <Id> node. Otherwise, a configuration error is thrown. is as follows:
Customer.hbm.xmml
"urn:nhibernate-mapping-2.2" namespace="Model"Assembly="Model" default-lazy="true"> <className="Model.customer, Model"Table="Customer"discriminator-value="0"lazy="false"> <!--unsaved-value="0"The primary key table does not need to be defined, but it needs to be defined in the child table--<id name= "CustomerId" column= "CustomerId" type= "int" unsaved-value= "0" > <gene Rator class= "native"/> <!--unsaved-value used to BES null and generator was increment in h2.0.3-< /id> <!--version label must be placed behind ID, otherwise error--<version name= "version"/>
......
Order.hbm.xml
<class name="model.order, Model" ="[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 is increment in h2.0.3- </id> <!--vers Ion tag must be placed behind ID, otherwise error-- <version name= "version"/>
-------------------------------------------------------------------
Use <version> tag configuration to implement concurrency control.
Rationale: Check the version value of the database's versions field: Before inserting, check if the version you are carrying is equal to the version value of the current database, if
"1" is equal, the insert succeeds, and the vesion is saved with the database.
"2" is unequal, the insertion fails, and throws an Nhibernate.staleobjectstateexception type exception, throwing an exception: so there is no need to nhibernate transaction support, rolling back and forth the transaction, because there is no insertion.
-------------------------------------Update concurrency Test------------------------------------------
Customer Update concurrency test:
[TestMethod] [ExpectedException ( typeof(nhibernate.staleobjectstateexception))] Public voidtestvessionbyupdate () {customerservice customerservice=NewCustomerService (); OrderService OrderService=NewOrderService (); Customer Customer=NewCustomer () {FirstName="Test", LastName="testvessionbyupdate", Age=Ten }; Customerservice.add (customer); Customer Customer1=Customerservice.get (Customer. CUSTOMERID); Customer Customer2=Customerservice.get (Customer. CUSTOMERID); stringCustomer1name ="Customer1"; Customer1. FirstName=Customer1name; Customer2. FirstName="customer2test"; customerservice.update (CUSTOMER2); Can be saved to the database, customer's version plus 1 customerservice.update (customer1); Throw Exception Nhibernate.staleobjectstateexception, the update failed.
}
Order Update concurrency Test:
[TestMethod] [ExpectedException ( typeof(nhibernate.staleobjectstateexception))] Public voidTestvessionorderbyupdatecustomer () {customerservice customerservice=NewCustomerService (); OrderService OrderService=NewOrderService (); Customer Customer=NewCustomer () {FirstName="Test", LastName="Testvessionorderbyupdatecustomer", Age=Ten }; Order Order1=NewOrder () {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); Both the customer and order can be saved to the database, and the order version plus 1 customerservice.update (customer1); Throws an exception nhibernate.staleobjectstateexception, the update fails.
}
Attention:
Note that the related code for the transaction has been commented out to illustrate that concurrency control above does not require transactional support. The code for Upadate is as follows:
Public voidUpdate (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 (); } }
-------------------------------------Delete (Update) the Concurrency test------------------------------------------
If concurrency is enabled (that is, the <version> tag attribute is added to the configuration),
Then the SQL where statement generated by the deletion will add an additional judging condition
where customer. Version = in the database. vesesion
Test code:
[TestMethod] [ExpectedException ( typeof(nhibernate.staleobjectstateexception))] Public voidTestvessiondeletecustomer () {customerservice customerservice=NewCustomerService (); OrderService OrderService=NewOrderService (); Customer Customer=NewCustomer () {FirstName="Test", LastName="Testvessiondeletecustomer", Age=Ten }; 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); }
As shown in the following:
If the same record is deleted concurrently, an exception of type nhibernate.staleobjectstateexception is thrown.