【问题标题】:NHibernate 3.2 By Code ClassMapping for Version PropertyNHibernate 3.2 By Code ClassMapping for Version 属性
【发布时间】:2011-12-01 22:21:49
【问题描述】:

使用 NHibernate 新的基于代码的映射在 SQL Server 2008 数据库中映射时间戳列的正确方法是什么?

我的类中的属性定义为 byte[],并且我在 ClassMapping 文件中使用以下映射:

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

但是,NHibernate 期望基于此映射的整数(插入时抛出异常)。如果我将映射类型明确指定为 byte[],我会收到一个异常说明:“System.ArgumentOutOfRangeException: Expected type implementation IUserVersionType 参数名称:persistentType”。

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

---编辑

我想我已经缩小了范围,我需要将映射上的 Type 设置为 BinaryType(实现 IVersionType 的 NHibernate 类型),但 BinaryType 没有公共构造函数......我想我已经不在了想法。

【问题讨论】:

    标签: c# .net nhibernate timestamp version


    【解决方案1】:

    如果您获取 NHib 源代码,测试项目中有一个类可以帮助您满足您的需求:NHibernate.Test.VersionTest.Db.MsSQL.BinaryTimestamp。基本上,您必须给它一个可用于转换值的自定义类型。默认情况下,NHib 期望该值是一个 int(查看the nhib docs 的第 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;
        }
    }
    

    使用该类的示例映射:

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

    【讨论】:

      【解决方案2】:

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

      这里是映射:

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

      更多详情请查看this link

      【讨论】:

      • 感谢您的回答,不幸的是我没有使用 Fluent Nhibernate。我只是使用 3.2 中新增的内置代码映射内置的代码映射没有 CustomSqlType
      【解决方案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);
                              });
                      }));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-25
        • 2015-03-21
        相关资源
        最近更新 更多