Entity Framework DB First: Timestamp column not working

Using the first db approach, I want my application to throw a concurrency exception whenever I try to update an (obsolete) entity that it supports a row in the database has already been updated by another application / user / session.

I am using Entity Framework 5 on .Net 4.5. The corresponding table has a Timestamp column to support the row version.

+4
source share
3 answers

I have done this in the past by adding a timestamp field to the table in which you want to perform a concurrency check. (in my example, I added a column called ConcurrencyCheck)

Depending on your needs, there are two types of concurrency mode:

1 concurrency Mode: Fixed:

Then re-add / update the table in your model. For fixed concurrency, make sure your concurrency mode is set to your table when importing into your model: for example,

enter image description here

Then, to catch this:

try { context.SaveChanges(); } catch (OptimisticConcurrencyException ex) { ////handle your exception here... 

2. concurrency mode: No

If you want to handle your own concurrency check, i.e. raise the validation informing the user and not even allowing to save, then you can set the concurrency mode to None.

1. Make sure that you change the ConcurrencyMode in the properties of the new column that you just added to "No." 2. To use this in my code, I would create a variable to save the current timestamp on the screen on which you want to check the save.

 private byte[] CurrentRecordTimestamp { get { return (byte[])Session["currentRecordTimestamp"]; } set { Session["currentRecordTimestamp"] = value; } } 

1.On loading (assuming that you are using asp.net and not mvc / razor, which you did not mention above), or when you fill the screen with the data you want to edit, I would pull the current record to Change the value of ConcurrencyCheck in this variable that you created.

  this.CurrentRecordTimestamp = currentAccount.ConcurrencyCheck; 

Then, if the user leaves the record open, and someone else changes it in the meantime, and then they also try to save, you can compare this timestamp value that you saved earlier with the concurrency value that it is now.

 if (Convert.ToBase64String(accountDetails.ConcurrencyCheck) != Convert.ToBase64String(this.CurrentRecordTimestamp)) { } 
+11
source

After reviewing many of the messages here and on the Internet explaining concurrency and timestamp in Entity Framework 5, I came to the conclusion that, in principle, it is not possible to get a concurrency exception when a model is created from an existing database.

One way is to modify the generated objects in the .edmx file and set the "Concurrency Mode" property of the timestamp of the "Fixed" object. Unfortunately, if the model is re-created from the database, this modification may be lost.

However, there is one difficult workaround:

  • Initialize a transaction scope with a re-read isolation level or higher

  • Get line timestamp

  • Compare the new timestamp with the old one.

  • Not Equal → Exception

  • Equals -> Commit Transaction

Isolation level is important to prevent simultaneous output modifications.

PS: The Erickset solution seems perfect to overcome the regeneration of the model file.

+4
source

EF detects a concurrency conflict if no rows are affected. Then, if you use stored procedures to delete and update, you can manually add the timestamp value to the where clause:

 UPDATE | DELETE ... WHERE PKfield = PkValue and Rowversionfield = rowVersionValue 

Then, if the row was deleted or changed by someone else, the Sql statement affects 0 rows, and EF interprets it as a concurrency conflict.

0
source

Source: https://habr.com/ru/post/1498414/


All Articles