Community & Support
Home / Community & Support / Knowledge Base / Telerik OpenAccess ORM / General / How to: Handle Optimistic Concurrency with OpenAccess

How to: Handle Optimistic Concurrency with OpenAccess

Article Info

Rating: Not rated

Article information

Article relates to

 Telerik OpenAccess ORM

Created by

 Zoran Kostov

Last modified

 June 01, 2009

Last modified by

 Zoran Kostov

One of the most challenging tasks for a web developer that is using OpenAccess is how-to handle the problems that might be caused by concurrent updates and deletes on the stored data. There are two approaches of handling the process in the appropriate manner - the first is involves using OpenAccessDataSource component for managing CRUD operations. All the logic for detecting and exposing a concurrent update or delete is built in the OpenAccessDataSurce and it is very straight-forward to track concurrent issues there.

When detecting such problem during an update or delete operation OpenAccessDataSource throws an OptimisticVerificationException which can be handled in the event handlers for the updating and deleting events.

In more advanced web projects though using a data source is not always an option. Queries are executed in code-behind and all CRUD operations are handled in that manner.

The answer for all concurrency concerns in those situations comes with the implementation of the IDataObjectKey interface to the persistent objects that are to be modified or deleted.

The IDataObjectKey property is a unique string for every persistent object that contains information about the identity and version of the object. Because the version of a persistent object is updated on modification this key can be used to give us information on weather a certain object has been modified.


Sample implementation:

There are entities of the Person type to be presented in a RadGrid. The grid is bound with a simple Linq query returning all the Person persistent objects from the database.

Our Person class implements the IDataObjectKey interface:
[Telerik.OpenAccess.Persistent(IdentityField = "id")] 
public class Person:IDataObjectKey 
   private int id; 
   [FieldAlias("id")] 
   public int Id 
   { 
        get { return id; } 
        set { id = value; } 
   } 
   ... 
 
  public string DataObjectKey 
  { 
      get{return Telerik.OpenAccess.DataObjectKey.Obtain(this);} 
  } 
 
The RadGrid has the edit command enabled. Our solution for the concurrent updates is the following:
•    When the Edit button is pressed we obtain the person object to be updated and store its DataObjectKey property into the Session state. We do that operation in the EditCommand event handler of the RadGrid:
protected void RadGrid1_EditCommand(object source, Telerik.Web.UI.GridCommandEventArgs e) 
    IDictionary values = new Hashtable(); 
    ((GridDataItem)e.Item).ExtractValues(values); 
    string id = (string)values["Id"]; 
    Person updatingPerson = (Person)scope.GetObjectById(Database.OID.ParseObjectId(typeof(Person), id)); 
    string keyAndVersion = updatingPerson.DataObjectKey; 
    Session["updatingPerson" + id.ToString()] = keyAndVersion;   
 
•    After typing the new values into the edit form of the grid the Update button is pressed. We obtain the record once again in the code-behind but this time using the static DataObjectKey.Check(string dataObjectKey, IObjectCotnext context) method. In this method OpenAccess checks if the instance represented by the DataObjectKey has been modified since the DataObjectKey was obtained. If the instance contains a new DataObjectKey e.g. it has a new version, an OptimisticVerificationException is thrown, else the persistent object is returned and we can commit an update on it.
protected void RadGrid1_UpdateCommand(object source, GridCommandEventArgs e) 
    { 
        IDictionary values = new Hashtable(); 
        ((GridEditableItem)e.Item).OwnerTableView.ExtractValuesFromItem(values,((GridEditableItem)e.Item)); 
 
        string id = (string)values["Id"]; 
        string keyAndVersionOld = (string)Session["updatingPerson" + id.ToString()]; 
        Person updatingPerson = (Person)DataObjectKey.Check(keyAndVersionOld, scope); 
        if (updatingPerson != null
        { 
            scope.Transaction.Begin(); 
            updatingPerson.Id = int.Parse(values["Id"].ToString()); 
            updatingPerson.FirstName = values["FirstName"].ToString(); 
            updatingPerson.LastName = values["LastName"].ToString(); 
            updatingPerson.AddressId = int.Parse(values["AddressId"].ToString()); 
            scope.Transaction.Commit(); 
            Session["updatingPerson" + id.ToString()] = null
        } 
    } 
 

From this point on it is fairly easy for one to implement his/her own logic for proceeding with the situation. For example the Check() method can be called in a try/catch block so if there is a  concurrency problem we can just prompt the user with appropriate message.
The code from the sample can be downloaded from Telerik OpenAccess Code Library.

Comments

There are no comments yet.
If you'd like to comment on this KB article, please, send us a Support Ticket.
Thank you!

Please Sign In to rate this article.