2011-12-01 6 views
5

NHibernateの新しいコードベースのマッピングを使用してSQL Server 2008データベースのタイムスタンプ列をマップする正しい方法は何ですか? (NHibernate 3.2バージョンプロパティによるクラスマッピング

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

しかし、NHibernateのは、このマッピングに基づいて、整数を期待している例外:

私は私のクラスのプロパティは、バイト[]として定義され、私は私のClassMappingファイルに次のマッピングを使用しています持っています挿入時の例外)。マッピングタイプをbyte []として明示的に指定すると、「System.ArgumentOutOfRangeException:IUserVersionTypeを実装する予想されるタイプ パラメータ名:persistentType」という例外が発生します。

自動更新タイムスタンプ列を新しいNHibernateコードベースのマッピングにマップする適切な方法は何ですか?

--- EDIT

私はそれが私がBinaryType(IVersionTypeを実装してNHibernateのタイプ)へのマッピングにタイプを設定する必要があることを絞り込ん持っていると思うが、BinaryTypeは、publicコンストラクタを持っていません。 ..私はアイデアがないと思う。

答えて

4

バージョンの実装にはbyte[] Version { get; }も使用しています。

詳細はまた
Version(x => x.Version) 
      .Nullable() 
      .CustomSqlType("timestamp") 
      .Generated.Always() 
      ; 

あなたはNHibのソースコードを入手した場合、あなたが必要なものをお届けしますテストプロジェクト内のクラスがありますthis link

+0

回答ありがとうございます。残念ながら、私はFluent Nhibernateを使用していません。私はちょうど3.2の新機能である組み込みのコードマッピングを使用しています。組み込みのby-codeマッピングにはCustomSqlTypeがありません – wllmsaccnt

5

参照してください。ここでは

が出マッピングです:NHibernate.Test.VersionTest.Db.MsSQL.BinaryTimestamp。基本的には、値を変換するために使用できるカスタムタイプを与える必要があります。デフォルトでは、NHibはその値がintであることを期待しています(0x34のseciont 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; 
    } 
} 

そのクラスを使用してサンプルマッピング:私は次の使用して終了ConventionModelMapperの場合

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 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); 
         }); 
       })); 
関連する問題