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

查看:21
本文介绍了使用具有值类型的 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',如何在 NHibernate 中使用 ValueType 实例作为组件?

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(存储 Ticks.当然你不需要这个分辨率.但是,你不应该为时区存储整小时,有 时区偏移了几分之一小时!!而且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天全站免登陆