2011-12-01 52 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); 
         }); 
       }));