将NHibernate ICompositeUserType与值类型一起使用

cod*_*zen 9 nhibernate orm value-type

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

我已经挖掘了如何使用NHibernate组件映射它,并发现它可以使用ICompositeUserType实例.但是,在实现接口时,我遇到了名为"SetPropertyValue"的方法,该方法表面上设置了类型中的属性.由于DateTimeOffset是一个System.ValueType,只是设置这样的属性是不可行的,因为它是不可变的(至少,没有使用一些反射或不安全的代码,我想避免).由于SetPropertyValue上的实例参数不是'ref',如何在NHibernate中使用ValueType实例作为组件?

Ste*_*ger 6

通过返回false in使用户类型为immutable,IsMutable并在其中抛出异常SetPropertyValue.

我有类似的东西,但有自己的数据类型而不是DateTimeOffset.我刚刚为你调整了代码.它将日期存储为UTC时间,偏移量TimeSpan存储为(存储Ticks.当然,您不需要此分辨率.但是,您不应该存储整个时间段的时区,有时区偏移小时数!而且TimeSpan是建立一个开箱即用的工程.)

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
Run Code Online (Sandbox Code Playgroud)