2011-12-01 51 views
5

使用NHibernate的基于新代码的映射映射SQL Server 2008数据库中的时间戳列的正确方法是什么?NHibernate 3.2按代码ClassMapping版本属性

我有我的类属性定义为字节[],我用我的ClassMapping文件下面的映射:

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

当然,NHibernate基于这种映射期待一个整数(抛出的插入异常)。如果我明确指定映射类型为byte [],则会得到一个异常,指出:“System.ArgumentOutOfRangeException:实现IUserVersionType的期望类型 参数名称:persistentType”。

什么是正确的方式来映射自动更新时间戳列与新的NHibernate基于代码的映射?

---编辑

我觉得我有它缩小,我需要设置类型的映射BinaryType(一个NHibernate的类型实现IVersionType),但BinaryType没有公共构造函数。我想我没有想法。

回答

4

我们还使用byte[] Version { get; }进行版本实现。

这里是出映射:

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

也为更多的详细信息,请参阅this link

+0

感谢您的回答,不幸的是我没有使用Fluent Nhibernate。我只是使用了3.2中新增的内置代码映射。内置的代码映射没有CustomSqlType – wllmsaccnt

5

如果你抢NHib源代码,有在测试项目中的一类,这将有助于你与你所需要的:NHibernate.Test.VersionTest.Db.MsSQL.BinaryTimestamp。基本上,你必须给它一个它可以用来转换值的自定义类型。默认情况下,NHib预计该值是一个整数(请参阅第012页的第5.1.7条)。如果使用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; 
    } 
} 

使用类A样本映射:

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>(); 
              }); 
    } 
} 
3

在ConventionModelMapper我结束了使用以下的情况下..

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); 
         }); 
       }));