Home > .Net, Dev > Optimistic Concurrency Control with MS Entity Framework and WCF or Webservices

Optimistic Concurrency Control with MS Entity Framework and WCF or Webservices

The Entity Framework makes it very simple to implement Optimistic Concurrency Control (OCC). To use this feature in combination with a disconnected application (Website/webservices), the recommend practice is to send both the original and the updated values of the object. This causes much larger network requests and could be done much more elegant.

How to use Optimistic Concurrency Control in ADO.Net Entity Framework using Webservices or WCF

Optimistic Concurrency Control in Entity framework
For using OCC in the Entity Framework you’ve got 2 options:
- using Stored Procedures
- Set the Concurrency Property of an object.

For both options I assume you make use of a rowversion (f.k.a. Timestamp) column in your table.

Stored Procedures
To use OCC in your stored procedures just compare the rowversion column with the version property in your object. If the match fails, don’t update any records. The update records value of 0 will raise an OptimisticConcurrencyException.

Using the Concurrency property
Open your EDMX Entity Model and select the version property mapped to the rowversion column of the table. Now select in the property window the Concurrency Mode property and select the value Fixed.

So far so good for the Entity Framework. But how does this work using webservices? Using other ORM (Object relational mapping) tools I was used to send the new values including the last known version. If the value of the version was equal to the version in the database the new values were written to the database. I would expect the same could be achieved using the Entity framework. When searching for this in the documentation I found the best practice to send both the original and the updated value. This means the messages to send to the webservices are twice as large a needed. The reason for this is that the objects are in detached state. The original object can now be attached to the context and the new values can be applied using ApplyPropertyChanges.

This can be done more efficiently! But I don’t want to write this code for every entity. So first I decided every Entity should implement an interface for Optimistic Concurrency Control. All Entities making use of OCC should have an ID and a version. The ID is mapped to the primary key (integer), the version is mapped to the Rowversion column.

/// <summary>
/// Interface to implement for every object using OCC
/// </summary>
public interface IOptimisticConcurrencyObject
{
/// <summary>
/// Id of the object
/// </summary>
int Id { get; set; }

/// <summary>
/// Version (timestamp/rowversion) of the object
/// </summary>
byte[] Version { get; set; }

Now implement a partial class for every entity making use of OCC.
For example my customer class:


public partial class Customer : IOptimisticConcurrencyObject
{
}

The next step is to append a generic method to the ObjectContext Class:


public partial class OCCEntities
{
/// <summary>
/// Add's a detached item to the object context
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="item"></param>
/// <returns></returns>
public T AddExistingObject<T>(T item) where T : EntityObject, IOptimisticConcurrencyObject, new()
{
T newItem;
string setname;

// create a new object
newItem = new T();

// set the id and version (timestamp) of the object
newItem.Id = item.Id;
newItem.Version = item.Version;

// get the setname of the object
setname = typeof(T).Name;

// Create a new key for the object
newItem.EntityKey = this.CreateEntityKey(setname, newItem);

// Attach the object to the context
this.AttachTo(setname, newItem);

// Apply all property changes of the detached object to the new object
this.ApplyPropertyChanges(setname, item);

return newItem;
}
}
This is all that’s needed. Now the update can be implemented in the service


/// <summary>
/// Update a customer
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public Customer UpdateCustomer (Booker.Contracts.Messages.UpdateCustomerMessage msg)
{
Customer updateCustomer;
BookerEntities ctx;

ctx = new BookerEntities();

// attach the object to the context
ctx.AddExistingObject<Customer>(msg.Customer);

try
{
ctx.SaveChanges();
}
catch (System.Data.OptimisticConcurrencyException)
{
// Throw your own functional exception instead of ApplicationException
throw new ApplicationException(“Optimistic Concurrency Exception occured”);
}

return msg.Customer;
}

  1. April 2nd, 2009 at 12:25 | #1

    Hi Raymond,

    Interesting post

    // Create a new key for the object
    newItem.EntityKey = this.CreateEntityKey(setname, newItem);

    returns a compile error .. does not contain a definition for ‘CreateEntityKey’ and no extension method ‘CreateEntityKey’ accepting a first argument …

    Did you mean CreateEntityKey on the ObjectContext?

  2. April 2nd, 2009 at 12:58 | #2

    @BartJ

    Yes in the example OCCEntities is the generated ObjectContext. AddExistingObject is added in the partial class of OCCEntities.
    In this example the IOptimisticConcurrencyObject contains an Id as primary key. A nicer way would be to implement a method to set the primary key values. In this way the primary key can also be another type or a combined primary key.

  1. No trackbacks yet.