【问题标题】:Mapping a DateTime property to an Int64 ticks column using NHibernate使用 NHibernate 将 DateTime 属性映射到 Int64 刻度列
【发布时间】:2010-12-22 08:56:27
【问题描述】:

我正在使用 Fluent NHibernate 映射到 Oracle 数据库表。

该表有一个代表日期的数字列。该数字表示刻度数,因此转换非常简单。我无法将类型更改为 Oracle 日期类型,因为其他应用程序使用相同的数据库。

我想在我的模型类中有一个 DateTime 属性:

public virtual DateTime Time { get; set; }

并将其映射到刻度列。我尝试使用

.CustomType(typeof(long))

但效果不太好,NHibernate 抛出了 System.InvalidCastException(我的猜测是 Int64 和 DateTime 之间的转换有问题)。

我必须实现 IUserType,还是有更简单的方法?

【问题讨论】:

    标签: nhibernate fluent-nhibernate nhibernate-mapping


    【解决方案1】:

    也许 IUserType 会有所帮助,但我自己从未这样做过。

    你可以做什么,作为一种解决方法:

    在你的类中创建 2 个属性:

    • 一个作为 DateTime 的公共属性
    • 一个拥有 TimeSpan 的私有财产

          private TimeSpan Ts
          {
              get;
              set;
          }
      
      
      
      public DateTime TheDate
      {
          get
          {
              return new DateTime (Ts.Ticks);
          }
          set
          {
              Ts = new TimeSpan (value.Ticks);
          }
      }
      

    将 NHibernate 映射中的私有属性映射到数据库中的特定列,以便 NHibernate 可以保存和检索值。 公共 DateTime 属性只是访问 TimeSpan 属性,并在其 getter 中将 Timespan 转换为 DateTime,并在其 setter 中设置 Timespan(将日期时间转换为时间跨度)。

    此解决方法的唯一缺点是您不能在查询中使用 DateTime 属性。 (除非您也映射此属性,并指定 NHibernate 不应保存此属性,但我不确定这是否可能)。

    【讨论】:

    • 谢谢,但这不是我想要的(我已经尝试过了,使用 long 而不是 TimeSpan)。我不想创建多余的属性。
    【解决方案2】:

    正如后续,这是一个处理此问题的 UserType 示例:

    public class DateTimeToTicksUserType : IUserType
    {
        public object Assemble(object cached, object owner)
        {
            return cached;
        }
    
        public object DeepCopy(object value)
        {
            return value;
        }
    
        public object Disassemble(object value)
        {
            return value;
        }
    
        public new bool Equals(object x, object y)
        {
            if (x == null) return false;
            return x.Equals(y);
        }
    
        public int GetHashCode(object x)
        {
            return x.GetHashCode();
        }
    
        public bool IsMutable
        {
            get { return false; }
        }
    
        public object NullSafeGet(IDataReader rs, string[] names, object owner)
        {
            object value = NHibernateUtil.Int64.NullSafeGet(rs, names);
    
            if (value == null)
            {
                return null;
            }
    
            return new DateTime((long) value);
        }
    
        public void NullSafeSet(IDbCommand cmd, object value, int index)
        {
            if (value == null)
            {
                NHibernateUtil.Int64.NullSafeSet(cmd, null, index);
                return;
            }
    
            value = ((DateTime) value).Ticks;
    
            NHibernateUtil.Int64.NullSafeSet(cmd, value, index);
        }
    
        public object Replace(object original, object target, object owner)
        {
            return original;
        }
    
        public Type ReturnedType
        {
            get { return typeof (DateTime); }
        }
    
        public SqlType[] SqlTypes
        {
            get { return new[] {new SqlType(DbType.Int64)}; }
        }
    }
    

    【讨论】:

      【解决方案3】:

      最终我实现了一个 IUserType。借助我在网上找到的一些示例,它非常简单。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-02-11
        • 2012-02-18
        • 2013-05-15
        • 2023-03-26
        • 2011-06-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多