使用NHibernate将DateTime属性映射到Int64 ticks列

时间:2010-12-22 08:56:27

标签: nhibernate fluent-nhibernate nhibernate-mapping

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

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

我想在我的模型类中使用DateTime属性:

public virtual DateTime Time { get; set; }

并将其映射到刻度线列。我试着用

.CustomType(typeof(long))

但它没有那么好用,NHibernate抛出了System.InvalidCastException(我的猜测是在Int64和DateTime之间存在问题)。

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

3 个答案:

答案 0 :(得分:2)

也许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属性,并将Timespan转换为其getter中的DateTime,并在其setter中设置Timespan(将datetime转换为timespan)。

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

答案 1 :(得分: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)}; }
    }
}

答案 2 :(得分:0)

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