If you do not wish to allow "client wins" approach or a "store wins" and you want to prevent any updates if a given record has been updated and force the user to re-load the record if they wish to proceed. Then this approach is for you.
In this way you can raise a validation to the user and tell them that the record is out of date and they need to reload it , or alternatively get the latest updated version from the database. However i would not recommend this approach because the the user is not updating the record the see on their screen. Therefore i would recommend forcing the user to re-open the record or refresh the screen.
This approach of managing concurrency uses the timestamp method.
1. Add a new column , of datatype Timestamp to the table on which you want to perform concurrency checks on. NB: Ensure it doesn't allow nulls
alter table XXX
2. Delete your table from your model in your .NET application and re-add it.add ConcurrencyCheck timestamp null
Implementing a concurrency mode of Fixed or None ??
Now you have your column in your database you have two ways to implement it.
There are two concurrency modes in Entity Framework:
So timestamps have a Concurrency Mode of Fixed, which means the original value loaded from the database is included in the WHERE clause of any Updates or Deletes. This means EF does the checking for your automatically.
If you want to use Fixed and let the EF handle your concurrency issues :
There are two concurrency modes in Entity Framework:
- None – This is the default and means the property is not involved in any concurrency checks
- Fixed – Which means that the original value of this property is sent as part of the WHERE clause in all updates or deletes
So timestamps have a Concurrency Mode of Fixed, which means the original value loaded from the database is included in the WHERE clause of any Updates or Deletes. This means EF does the checking for your automatically.
If you want to use Fixed and let the EF handle your concurrency issues :
Using Concurrency Mode : Fixed
- Ensure you change the ConcurrencyMode in the properties of the new column you just added to "Fixed".
If you set it to Fixed then you just have to trap an Optimistic concurrency error when you save the context.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
try
{
context.SaveChanges();
}
catch (OptimisticConcurrencyException ex) {
////handle your exception here...
Using Concurrency Mode : None
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
| try
{
context.SaveChanges();
}
catch (OptimisticConcurrencyException ex) {
////handle your exception here...
|
Using Concurrency Mode : None
If you wish to handle your own concurrency checking , i.e. raise a validation informing the user and not even allowing a save to occur then you can set Concurrency mode None.
- Ensure you change the ConcurrencyMode in the properties of the new column you just added to "None".
- To use this in your code , i would create a variable to store your current timestamp on the screen you which to check a save on.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
| private byte[] CurrentRecordTimestamp
{
get
{
return (byte[])Session["currentRecordTimestamp"];
}
set
{
Session["currentRecordTimestamp"] = value;
}
}
|
- On screen load , or when you populate the screen with the data you wish you edit , i would pull out the current record under edit's ConcurrencyCheck value into this variable you created
1:
2:
3:
4:
| private void PopulateScreen()
{
this.CurrentRecordTimestamp = currentAccount.ConcurrencyCheck;
|
Then if the user leaves the record open , and someone else in the meantime changes it , and then they also attempt to save , you can compare this timestamp value you saved earlier with the concurrency value it is now.
1:
2:
3:
| If (Convert.ToBase64String(accountDetails.ConcurrencyCheck) !=
Convert.ToBase64String(this.CurrentRecordTimestamp))
{
}
|
No comments:
Post a Comment