Sony Arouje

a programmer's log

Unix timestamp version type in NHibernate

with one comment

The system I am working now uses NHibernate as ORM. It’s a web service with concurrent users. So one of the core issue I need to resolve is concurrency. NHibernate support different types of concurrency models, Ayende has a good post explaining about the supported concurrency models in NHibernate. From the model I choose Versioned model because our service running in sessionless detached mode, and version is the better approach here.

From Ayende’s post, we can see NHibernate version supports below types.

  • Numeric
  • Timestamp
  • DB Timestamp

The database I am working is a legacy one and different apps using it. So concurrency check is spread across the system and the existing system uses a Unix timestamp field to check concurrency. So the webservice should also use the same field. But the issue here is this field not fall under any of the supported version type.

One of the great feature of NHibernate is, we can expand it’s functionality, we can add new user types, add new listeners, interceptors, etc. So I started thinking in that direction, to create a new Version type for Unix timestamp field. After some research in NHibernate I figured out that version type can be extended by implementing IUserVersionType. Now I know what to do, just implement IUserVersionType and add the required logic to create unix timestamp. Below is the new version type I created.

public class UnixTimestampVersion : IUserVersionType
{
    private static readonly NHibernate.SqlTypes.SqlType[] SQL_TYPES =
{ NHibernate.NHibernateUtil.Int64.SqlType };

    public object Next(object current, NHibernate.Engine.ISessionImplementor session)
    {
        return DateUtil.CurrentDateInUnixFormat();
    }

    public object Seed(NHibernate.Engine.ISessionImplementor session)
    {
        return Int64.MinValue;
    }

    public object Assemble(object cached, object owner)
    {
        return cached;
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Disassemble(object value)
    {
        return value;
    }

    public new bool Equals(object x, object y)
    {
        if (object.ReferenceEquals(x, y)) return true;
        if (x == null || y == null) return false;
        return x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        if (x == null)
            return 0;

        return x.GetHashCode();
    }

    public bool IsMutable
    {
        get { return false; }
    }
    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
       return NHibernateUtil.Int64.NullSafeGet(rs, names[0]);
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
       NHibernateUtil.Int64.NullSafeSet(cmd, Convert.ToInt64(value), index);
    }
    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public Type ReturnedType
    {
        get { return typeof(Int64); }
    }

    public NHibernate.SqlTypes.SqlType[] SqlTypes
    {
        get { return SQL_TYPES; }
    }

    public int Compare(object x, object y)
    {
        return ((Int64)x).CompareTo((Int64)y);
    }
}

IUserVersionType has a Next function, there we need to implement the functionality to create the next value for the timestamp. I have a DateUtil that creates the Unix timestamp based on the current time. Let’s see how to use the new version type in hbm mapping file.

<hibernate-mapping default-access="property" xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
   <class name="Myapp.Domain.User,Myapp.Domain" lazy="true" table="CLASIX_USER"
       optimistic-lock="version"
       dynamic-update="true"
       select-before-update="true">
    <id name="UserName" column="USERNAME" access="property"/>    
    <version name="ChangeDate" column="CHANGE_DATE"
          type="Myapp.Infrastructure.Persistence.UnixTimestampVersion,
          MyAppp.Infrastructure.Persistence"/>
  </class>
</hibernate-mapping>

It’s very easy to configure the new version type in NHibernate mapping, see the configuration in bold italics.

Happy coding…

Advertisements

Written by Sony Arouje

April 9, 2013 at 2:29 pm

One Response

Subscribe to comments with RSS.

  1. […] it’s updated using Automapper, while converting DTO to Entity. I use unix timestamp as version and we added a custom mapping in automapper to fill current date in unix timestamp format if […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: