News, examples, tips, ideas and plans.
Thoughts around ORM, .NET and SQL databases.

Tuesday, November 12, 2013

Enhancement in optimistic concurrency mode

Starting from DataObjects.Net 4.6.4 we are introducing an update to optimistic concurrency feature — server-side version check.

The present API of optimistic concurrency feature in DataObjects.Net with all these VersionSet, VersionCapturer, VersionValidator, whatever is kind of tricky, over-complicated and mind-blowing, so eventually we started moving towards more simple and transparent solution. The server-side version check is the first step in this direction.

The whole idea of server-side version check is obvious: each time an entity is fetched from database, it is associated with a version. On each successful update version is incremented. Each UPDATE command contains additional check for the specific version. Here is an example:

Say, we operate an online book store and use the following simplified Book model with Version field for optimistic concurrency check:

[HierarchyRoot]
public class Book : Entity
{
    [Field, Key]
    public int Id { get; set; }

    [Field(Length = 128)]
    public string Title { get; set; }

    [Field, Version]
    public int Version { get; set; }

    public Book(Session session) : base(session)
    {}
}

As the field is marked with VersionAttribute, DataObjects.Net detects and uses it to store the Book version which is automatically incremented after each successfully committed transaction. Now we want that every update command to include the additional check for version, e.g.:

UPDATE [dbo].[Book]  
SET [Title] = 'DataObjects.Net 4 unleashed' 
WHERE (([Book].[Id] = 123) AND ([Book].[Version] = 2)); 

If this check fails, the Xtensive.Orm.VersionConflictException is thrown with message "Version of entity with key 'Book, (123)' differs from the expected one", so it can be easily detected and handled.

By default, this mode in DataObjects.Net 4.6.4. is switched off to provide compatibility with the older versions. To switch it on we should change SessionConfiguration like this:

var sessionConfig = new SessionConfiguration(
    SessionOptions.ServerProfile | SessionOptions.ValidateEntityVersions);

using (var session = domain.OpenSession(sessionConfig)) {
    // do some stuff 
}

Alternatively, this can be done in configuration file so it is automatically applied to all sessions, like this:

<Xtensive.Orm>
    <domains>
      <domain name="Default"
              upgradeMode="Recreate"
              connectionUrl="sqlserver://localhost/AmazonBookStore">
        ...
        <sessions>
          <session name="Default" options="ServerProfile, ValidateEntityVersions" />
        </sessions>
      </domain>
    </domains>
  </Xtensive.Orm>

No comments:

Post a Comment