使用具有值类型的NHibernate ICompositeUserType [英] Using NHibernate ICompositeUserType with a value type

查看:96
本文介绍了使用具有值类型的NHibernate ICompositeUserType的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个域模型对象,该对象的属性类型为System.DateTimeOffset.我正在使用一个本机不支持此类型的数据库,因此我打算使用类型为'datetime'的列和类型为'smallint'的列来存储它.

I have a domain model object which has properties of type System.DateTimeOffset. I'm using a database which doesn't support this type natively, so I'm planning to store it using a column of type 'datetime' and one of type 'smallint'.

我研究了如何使用NHibernate组件对此进行映射,并发现它可以使用ICompositeUserType实例来工作.但是,在实现接口后,我遇到了一种名为"SetPropertyValue"的方法,该方法表面上在类型内设置了一个属性.由于DateTimeOffset是System.ValueType,因此仅设置这样的属性是不起作用的,因为它是不可变的(至少,在不使用某些反射或不安全代码的情况下,我想避免这种情况).由于SetPropertyValue上的实例参数不是'ref',因此如何将ValueType实例用作NHibernate中的组件?

I've dug around on how to map this using NHibernate components, and found that it could work using an ICompositeUserType instance. However, upon implementing the interface, I've come across the method called "SetPropertyValue" which ostensibly sets a property within the type. Since DateTimeOffset is a System.ValueType, just setting a property like this won't work since it is immutable (at least, without using some reflection or unsafe code, which I'd like to avoid). Since the instance parameter on SetPropertyValue isn't 'ref' how does one use ValueType instances as components in NHibernate?

推荐答案

通过在IsMutable中返回false并在SetPropertyValue中仅引发异常,使用户类型不可变.

Make the user type immutable by returning false in IsMutable and just throw an exception in SetPropertyValue.

我有类似的东西,但是具有自己的数据类型而不是DateTimeOffset.我只是为您改编了代码.它将日期存储为UTC时间,将偏移量存储为TimeSpan(存储刻度).的时间!并且TimeSpan是内置于现成的作品中的.)

I have something similar, but with an own datatype instead of DateTimeOffset. I just adapted the code for you. It stores the date as UTC time and the offset as TimeSpan (stores Ticks. Of course you don't need this resolution. But, you should not store whole hours for time zones, there are time zones offsets with fractions of hours!! And TimeSpan is build in an works out of the box.)

public class DateTimeOffsetUserType : ICompositeUserType
{
    public bool IsMutable
    {
        get { return false; }
    }

    public void SetPropertyValue(object component, int property, object value)
    {
        throw new InvalidOperationException("Immutable, SetPropertyValue is not allowed");
    }

    public object NullSafeGet(System.Data.IDataReader dr, string[] names, NHibernate.Engine.ISessionImplementor session, object owner)
    {
        if (dr == null)
        {
            return null;
        }

        DateTime? utcTime;
        TimeSpan? offset;

        utcTime = (DateTime?)PropertyTypes[0].NullSafeGet(dr, names[0], session, owner);
        offset = (TimeSpan?)PropertyTypes[1].NullSafeGet(dr, names[1], session, owner);

        if (utcTime == null || offset == null) return null;
        return new DateTimeOffset(utcTime.Value, offset.Value);
    }

    public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index, NHibernate.Engine.ISessionImplementor session)
    {
        if (value == null)
        {
            NHibernateUtil.Timestamp.NullSafeSet(cmd, null, index);
            NHibernateUtil.TimeSpan.NullSafeSet(cmd, null, index + 1);
        }
        else
        {
            DateTimeOffset dateTimeOffset = (DateTimeOffset)value;

            PropertyTypes[0].NullSafeSet(cmd, dateTimeOffset.UtcDateTime, index, session);
            PropertyTypes[1].NullSafeSet(cmd, dateTimeOffset.Offset, index + 1, session);
        }

    }

    // other methods

这篇关于使用具有值类型的NHibernate ICompositeUserType的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆