EntityFramework 6 (EF6 DBcontext) Concurrent processing practices, entityframeworkef6

Source: Internet
Author: User

EntityFramework 6 (EF6 DBcontext) Concurrent processing practices, entityframeworkef6

Learning:C # comprehensive secrets-detailed description of Entity Framework concurrent processingPost notesThe post uses objectContext,

I. Concurrency related concepts

Concurrency type:

The first mode is pessimistic concurrency, that is, when a user is modifying a record, the system will reject other users from simultaneously modifying this record.
The second mode is optimistic concurrency, that is, the system allows multiple users to modify the same record at the same time. The system will pre-define the concurrent exception handling mode caused by data concurrency, handle possible conflicts after modification. There are several common Optimistic Concurrency processing methods:

1. retain the last modified value.
2. Retain the original modified value.
3. Merge the modified values multiple times.

Ii. Concurrent processing options for model attributes

For example, the TimeStamp field in the Model Designer enables concurrency.

<EntityType Name="UserAccout">          <Key>            <PropertyRef Name="Id" />          </Key>          <Property Name="Id" Type="Int32" Nullable="false" annotation:StoreGeneratedPattern="Identity" />          <Property Name="FirstName" Type="String" Nullable="false" />          <Property Name="LastName" Type="String" Nullable="false" />          <Property Name="AuditFileds" Type="OrderDB.AuditFields" Nullable="false" />          <Property Name="Timestamp" Type="DateTime" Nullable="false" ConcurrencyMode="Fixed" annotation:StoreGeneratedPattern="Computed" />        </EntityType>

Concurrency mode: ConcurencyMode has two members:

None: This attribute is never verified during write operations. This is the default concurrency mode.

Fixed: always verify this attribute when writing.

When the default value is None, the system does not detect this model attribute. When this attribute is modified at the same time, the system processes the INPUT attribute values in data merging mode.

When the model attribute is Fixed, the system checks the model attribute. When the attribute is modified at the same time, the system will trigger OptimisticConcurrencyException.

Iii. pessimistic concurrency

 

4. Optimistic Concurrency

To solve the problem caused by pessimistic concurrency, ADO. NET Entity Framework provides a more efficient Optimistic Concurrency processing method. Compared with LINT to SQL, ADO. NET Entity Framework simplifies the processing of Optimistic Concurrency. It can flexibly use Merge data, retain the first input data, and retain the latest input data (three methods) to handle concurrent conflicts.
4.1 merge Concurrent Data

Summary: When the ConcurencyMode of the model attribute is set to the default value None, once the same object attribute is modified at the same time, the system will process concurrency conflicts by merging data, this is also the default way for Entity Framework to handle concurrency conflicts.

The merge processing method is as follows:

(1) When the attribute of the same object is modified at the same time, the system will save the newly entered attribute value.

(2) When different attributes of the same object are modified at the same time, the system will save the modified attribute values. Here are two examples:

Running result:

# When the region (4.1) test does not set any concurrency test, when the processing method of the concurrent EF is delegate void MyDelegate (Address addressValue); public StringBuilder sb = new StringBuilder (); public Address GetAddress (int id) {using (OrderDBContainer context = new OrderDBContainer () {IQueryable <Address> list = context. addressSet. where (x => x. id = id); return list. first () ;}/// <summary> // modification method // </summary> /// <param name = "addressValue"> </param> Public void UpdateAddress (Address addressValue) {using (OrderDBContainer context = new OrderDBContainer () {// Display the information of new data input ("Current", addressValue ); var obj = context. addressSet. where (x => x. id = addressValue. id ). first (); if (obj! = Null) context. entry (obj ). currentValues. setValues (addressValue); // virtual operation to ensure that data can be added to the context at the same time. sleep (1, 100); context. saveChanges ();}} /// <summary> /// display the current attributes of the object /// </summary> /// <param name = "message"> </param> /// <param name = "addressValue"> </param> public void Display (string message, address addressValue) {String data = string. format ("{0} \ n Address Message: \ n Id: {1} Address1: {2}" + "address2: {3} \ r \ n", message, addressValue. id, addressValue. address1, addressValue. address2); sb. appendLine (data) ;}/// <summary> /// (1) Test the default EF mechanism. When concurrency control is configured, the merge method is used. // </summary> /// <param name = "sender"> </param> /// <param name = "e"> </param> private void button3_Click (object sender, eventArgs e) {// Display the object information var beforeObj = GetAddress (1); Display ("Before", beforeObj) Before updating data; // update the SecondName of Person, age two attributes: Address _ address1 = new Address (); _ address1.Id = 1; _ address1.Address1 = "Gu Xi"; _ address1.Address2 = beforeObj. address2; _ address1.AuditFields. insertDate = beforeObj. auditFields. insertDate; _ address1.AuditFields. updateDate = beforeObj. auditFields. updateDate; _ address1.City = beforeObj. city; _ address1.Zip = beforeObj. zip; _ address1.State = beforeObj. state; // update the FirstName attribute Address _ address2 = new Address (); _ address2.Id = 1; _ address2.Address1 = beforeObj. address1; _ address2.Address2 = "Jiangsu"; _ address2.AuditFields. insertDate = beforeObj. auditFields. insertDate; _ address2.AuditFields. updateDate = beforeObj. auditFields. updateDate; _ address2.City = beforeObj. city; _ address2.Zip = beforeObj. zip; _ address2.State = beforeObj. state; // use the Asynchronous Method to simultaneously update the data MyDelegate myDelegate = new MyDelegate (UpdateAddress); myDelegate. beginInvoke (_ address1, null, null); myDelegate. beginInvoke (_ address2, null, null); Thread. sleep (1000); // Display the object information var afterObj = GetAddress (1); Display ("After", afterObj); this. textBox1.Text = sb. toString ();} /// <summary> /// insert several pieces of data for testing. /// </summary> /// <param name = "sender"> </param> // /<param name = "e"> </param> private void BtnSaveAddress_Click (object sender, eventArgs e) {using (OrderDBContainer db = new OrderDBContainer () {Address address = new Address (); address. address1 = "Gu Xi Town"; address. address2 = "Anzhen"; address. state = "2"; address. city = "Wuxi"; address. auditFields. insertDate = DateTime. now; address. auditFields. updateDate = DateTime. now; address. zip = "21415"; db. addressSet. add (address); db. saveChanges () ;}/// <summary> /// restore to the initial value, prepare to test again /// </summary> /// <param name = "sender"> </param> /// <param name = "e"> </param> private void button5_Click (object sender, eventArgs e) {using (OrderDBContainer db = new OrderDBContainer () {Address _ address = db. addressSet. where (x => x. id = 1 ). first (); _ address. address1 = "aaa"; _ address. address2 = "bbb"; db. saveChanges () ;}# endregion

Remarks: problems encountered in practice

In multi-thread mode, attach cannot be used to modify the event solution of EF:

An error is returned when an Entry is used.

Refer to the following post

/// <Summary> /// modification method /// </summary> /// <param name = "addressValue"> </param> public void UpdateAddress (Address addressValue) {using (OrderDBContainer context = new OrderDBContainer () {// Display the information of the new data input ("Current", addressValue); var obj = context. addressSet. where (x => x. id = addressValue. id ). first (); if (obj! = Null) context. entry (obj ). currentValues. setValues (addressValue); // virtual operation to ensure that data can be added to the context at the same time. sleep (1, 100); context. saveChanges ();}}

Reference:"Processing concurrent conflicts by means of data merging is convenient and fast, but this processing method is not suitable for systems with complicated business logic. For example, in a common Order and OrderItem table, the unit price and quantity of OrderItem directly affect the overall price of Order. In this way, concurrent processing by merging data may cause logical errors. In this case, you should consider handling concurrency conflicts in other ways .".

What are the other methods? [To be supplemented]

 

4.1Delete and update operations run simultaneously (non-framework automatic processing capability, manually added by developers to manually modify the status)

Entity Framework can flexibly process operations that update the same object at the same time with a sound mechanism. However, when both the delete and update operations run simultaneously, logical exceptions may exist.

For example, two clients load the same object at the same time. After the first client updates the data, it submits the data again. However, before submission, the second client has deleted the existing data in the database.

In this case, the objects in the context are in different States, and the OptimisticConcurrencyException will be thrown. (the exceptions are different in ObjectContext and DBContext. You must determine the exceptions based on the test results ).
When this exception occurs, you can use try (OptimisticConcurrencyException) {...} catch {...} to catch the exception, and then change the object's State attribute. Change EntityState to Added, and the deleted data will be loaded again. If the EntityState is changed to Detached, the data will be deleted smoothly. The following example shows how to change the EntityState attribute of an object to Added.

The Code is as follows: the ID changes before and after the processing result (maybe this is one of the reasons why some architects use manually created guids instead of auto-increment, because the ID cannot be returned after the data is deleted, and it is not too flexible. Using GUID combined with the dataVison field, timeStamp is enough to control data concurrency.

// Update object public int UpdateWithConcurrent (int num, Address addressValue) {int returnValue =-1; using (OrderDBContainer context = new OrderDBContainer () {var obj = context. addressSet. where (x => x. id = addressValue. id ). first (); // display the status of the object DisplayState ("Before Update", obj); try {if (obj! = Null) context. entry (obj ). currentValues. setValues (addressValue); // virtual operation to ensure that data has been asynchronously deleted from the database Thread. sleep (1, 300); context. saveChanges (); returnValue = obj. id;} catch (Exception) {// determine the Exception, because I only tested the deletion, write to Added directly. // the correct one is to determine whether to modify or delete OptimisticConcurrencyException ex // change the object state to Added context. entry (obj ). state = System. data. entity. entityState. added; context. saveChanges (); returnValue = obj. id ;}} return returnValue ;}

Exception type during concurrency:

ID changed

 

4.3 When data concurrency occurs, the final (latest: Last) input data is retained

To verify the attributes of the input object, you must first set the ConcurencyMode of the attribute to Fixed, so that the system will detect the input values of the object attribute in real time.
When this attribute is updated at the same time, the OptimisticConcurrencyException is thrown. After capturing this exception, you can use ObjectContext. refresh (RefreshMode, object) refreshes the state of the object in the context. When RefreshMode is ClientWins, the system will keep the current data in the context, that is, keep the latest input object value. Then, use ObjectContext. SaveChanges to add the latest input object value to the database.

In the following example, before the system starts, set the ConcurencyMode attribute of the FirstName and SecondName attributes of Person to Fixed so that the system can monitor changes to these two attributes. The entered data is modified only in the FirstName and SecondName values. Before submitting data, use the DisplayProperty method to display the original data attributes of the database. After the data is updated for the first time, call DisplayProperty again to display the updated data attributes. When the data is updated for the second time, ObjectContext is called. when SaveChanges, the data in the database has been modified, and there is a conflict with the data in the current context ObjectContext. The system will trigger the OptimisticConcurrencyException exception and display the object attributes that cause the exception again. After the exception is processed, the final object Value in the database is displayed.

 

 

Observe the test results. When the RefreshMode status is ClientWins, the system will save the object attributes in the context. This method can be used to keep the latest input object attributes in the case of concurrent exceptions.

 

4.4 When data concurrency occurs, the earliest (first time) input data is retained.

After you set the ConcurencyMode of the object property to Fixed and update the property, OptimisticConcurrencyException is thrown. In this case, ObjectContext. Refresh (RefreshMode, object) is used to Refresh the state of the object in the context. When RefreshMode is StoreWins, the system replaces the data in the data source with the data in the context.
Because SaveChanges is called for the first time, the data can be successfully saved to the database. However, if the ObjectContext is not released and the SaveChanges is used again to asynchronously update data, the OptimisticConcurrencyException concurrency exception is thrown. When the RefreshMode is StoreWins, the system retains the attribute of the first input data.
This example is very similar to the above example. It is just to change RefreshMode to StoreWins. In systems with complex business logic, we recommend that you use this method to handle concurrency exceptions. After the attribute is modified, the attribute is returned to the customer, and the customer can make a comparison before deciding the next processing method.

Observe the test results. When the RefreshMode status is StoreWins, the system replaces the object attribute in the context with the data in the data source. In systems with complex business logic, we recommend that you use this method to handle concurrency exceptions.

Link: https://pan.baidu.com/s/1gfu6fZl password: fyb3

Exercise source code. If you have any corrected errors, remember to share them.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.