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

发布于 2024-10-08 11:04:40 字数 435 浏览 0 评论 0原文

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

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

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

public virtual DateTime Time { get; set; }

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

.CustomType(typeof(long))

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

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

I'm using Fluent NHibernate to map to an Oracle database table.

The table has a number column that represents a date. The number represents the number of ticks, so the conversion is pretty straightforward. I can't change the type to an Oracle date type because other applications use the same database.

I'd like to have a DateTime property in my model class:

public virtual DateTime Time { get; set; }

and map it to the ticks column. I tried to use

.CustomType(typeof(long))

but it didn't work so well, NHibernate threw a System.InvalidCastException (my guess is that there was a problem casting between an Int64 and a DateTime).

Must I implement an IUserType, or is there a simpler way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜扑 2024-10-15 11:04:40

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

您可以做的解决方法是:

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

  • 一个是 DateTime 的公共属性
  • 一个包含 TimeSpan 的私有属性

     私有时间跨度 Ts
        {
            得到;
            放;
        }
    
    
    
    公共 DateTime TheDate
    {
        得到
        {
            返回新的日期时间(Ts.Ticks);
        }
        放
        {
            Ts = new TimeSpan(value.Ticks);
        }
    }
    

NHibernate 映射中的私有属性映射到数据库中的特定列,以便 NHibernate 可以保存和检索该值。
公共 DateTime 属性仅访问 TimeSpan 属性,并在其 getter 中将 Timespan 转换为 DateTime,并在其 setter 中设置 Timespan(将 datetime 转换为 timespan)。

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

Perhaps an IUserType would help, but I've never done this myself.

What you can do, as a workaround is this:

Create 2 properties in your class:

  • one public property that is a DateTime
  • one private property that holds a TimeSpan

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

Map the private property in your NHibernate mapping to the specific column in the database, so that NHibernate can save and retrieve the value.
The public DateTime property just accesses the TimeSpan property, and converts the Timespan to a DateTime in its getter, and sets the Timespan (convert datetime to timespan) in its setter.

The only disadvantage of this workaround, is that you cannot use the DateTime property in your queries. (Unless you map this property as well, and specify that NHibernate should not save this property, but I'm not sure if this is possible).

夢归不見 2024-10-15 11:04:40

正如后续,这里是处理此问题的 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)}; }
    }
}

Just as follow up, here's an example of a UserType which handles this:

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)}; }
    }
}
稀香 2024-10-15 11:04:40

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

Eventually I implemented an IUserType. With the help of some examples I found on the web, it was pretty straightforward.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文