NHibernate 3.2. CodeMapping Class for Version Property

What is the correct way to map a timestamp column in a SQL Server 2008 database using mappings based on new NHibernate code?

I have a property in my class defined as byte [], and I use the following mapping in the ClassMapping file:

Version(x => x.RowVersion, mapping =>
   mapping.Generated(VersionGeneration.Always));

However, NHibernate expects an integer based on this mapping (throws an exception for attachments). If I explicitly specify the display type as byte [], I get an exception: "System.ArgumentOutOfRangeException: expected implementation type IUserVersionType Parameter name: persistentType".

What is the correct way to map an auto-update timestamp column to new NHibernate-based mappings?

--- EDIT

I think I narrowed it down, I need to set Type to BinaryType mapping (the NHibernate type that implements IVersionType), but BinaryType does not have a public constructor ... I think I'm not in an idea.

+5
source share
3 answers

We also use byte[] Version { get; }to implement the version.

The mappings are displayed here:

Version(x => x.Version)
            .Nullable()
            .CustomSqlType("timestamp")
            .Generated.Always()
            ;

Also see this link for more information.

+4
source

NHib, , , : NHibernate.Test.VersionTest.Db.MsSQL.BinaryTimestamp. , , . NHib , int ( seciont 5.1.7 nhib docs). int/bigint , .

( NHib):

public class BinaryTimestamp : IUserVersionType
{
    #region IUserVersionType Members

    public object Next(object current, ISessionImplementor session)
    {
        return current;
    }

    public object Seed(ISessionImplementor session)
    {
        return new byte[8];
    }

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

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

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

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        return rs.GetValue(rs.GetOrdinal(names[0]));
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        NHibernateUtil.Binary.NullSafeSet(cmd, value, index);
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public System.Type ReturnedType
    {
        get { return typeof(byte[]); }
    }

    public SqlType[] SqlTypes
    {
        get { return new[] { new SqlType(DbType.Binary, 8) }; }
    }

    public int Compare(object x, object y)
    {
        var xbytes = (byte[])x;
        var ybytes = (byte[])y;
        return CompareValues(xbytes, ybytes);
    }

    bool IUserType.Equals(object x, object y)
    {
        return (x == y);
    }

    #endregion

    private static int CompareValues(byte[] x, byte[] y)
    {
        if (x.Length < y.Length)
        {
            return -1;
        }
        if (x.Length > y.Length)
        {
            return 1;
        }
        for (int i = 0; i < x.Length; i++)
        {
            if (x[i] < y[i])
            {
                return -1;
            }
            if (x[i] > y[i])
            {
                return 1;
            }
        }
        return 0;
    }

    public static bool Equals(byte[] x, byte[] y)
    {
        return CompareValues(x, y) == 0;
    }
}

:

public class Car
{
    public virtual long CarId { get; set; }
    public virtual string Name { get; set; }
    public virtual byte[] LastModified { get; set; }

    public override string ToString()
    {
        return string.Format("Id: {0}, Name: {1}, Last Modified: {2}", CarId, Name, LastModified);
    }
}

public class CarMap : ClassMapping<Car>
{
    public CarMap()
    {
        Table("Cars");

        Id(car => car.CarId, mapper => mapper.Generator(Generators.Identity));
        Property(car => car.Name);
        Version(car => car.LastModified, mapper =>
                                             {
                                                 mapper.Generated(VersionGeneration.Always);
                                                 mapper.Type<BinaryTimestamp>();
                                             });
    }
}
+5

In the case of the ModelMapper conjunct, I ended up using the following.

ConventionModelMapper mapper = new ConventionModelMapper();

//...other mappings

mapper.Class<Entity>(map => map.Version(e => e.Revision, m =>
                {
                    m.Generated(VersionGeneration.Always);
                    m.UnsavedValue(null);
                    m.Type(new BinaryBlobType());
                    m.Column(c =>
                        {
                            c.SqlType("timestamp");
                            c.NotNullable(false);
                        });
                }));
+3
source

All Articles