Вопрос по orm, nhibernate, value-type – Использование NHibernate ICompositeUserType с типом значения

9

У меня есть объект модели домена, который имеет свойства типа System.DateTimeOffset. Я использую базу данных, которая изначально не поддерживает этот тип, поэтому я планирую сохранить ее с использованием столбца типа «datetime». и один из типов «smallint».

Я покопался в том, как отобразить это с помощью компонентов NHibernate, и обнаружил, что он может работать с использованием экземпляра ICompositeUserType. Однако после реализации интерфейса я столкнулся с методом, называемым «SetPropertyValue». который якобы устанавливает свойство в типе. Поскольку DateTimeOffset является System.ValueType, просто установка свойства, подобного этому, не будет работать, поскольку оно является неизменным (по крайней мере, без использования некоторого отражения или небезопасного кода, которого я хотел бы избежать). Поскольку параметр экземпляра в SetPropertyValue не является "t" ref ". как использовать экземпляры ValueType в качестве компонентов в NHibernate?

Ваш Ответ

3   ответа
2

Насколько я понимаю, если тип, с которым вы сопоставляете, и ICompositeUserType является неизменяемым, SetPropertyValue () вообще ничего не должен делать или даже генерировать исключение, поскольку nhibernate не должен его вызывать.

0
public void SetPropertyValue(object component, int property, object value)

У меня есть код, который реализует DateTime из двух полей int.

Код, по сути, представляет собой свойство включения (0 - дата, 1 - время, в моем случае), и в конце каждого оператора case объекту компонента присваивается новый экземпляр DateTime.

свойство = 0 (дата):

// code to calculate year, month, day from object value
DateTime dt = (DateTime)component;
dt = new DateTime(year, month, day, dt.Hour, dt.Minute, dt.Second);

свойство = 1 (время):

// code to calculate hours, minutes, seconds from object value
DateTime dt = (DateTime)component;
dt = new DateTime(dt.Year, dt.Month, dt.Day, hours, minutes, seconds);

Понятия не имею, хорошо это или плохо, но это работает для меня (иначе у меня нет проблем с изменением того, на что указывает компонент, ссылка или нет).

Я не уверен, есть ли документация этого материала. Я даже не помню этого, и мне пришлось смотреть на контекст в моем коде. Я думаю, что мне пришлось посмотреть на пример, обычно предоставляемый с NHibernate (я думаю, что это две строки?) И извлечь уроки из этого (и, очевидно, забыть об этом, как только я закончу!)
Я просто сбит с толку тем, как можно заставить это работать, поскольку DateTime является ValueType. Как только вы распакуете его на локальный "dt" вы делаете его копию, и все изменения теряются при выходе из метода. В этом суть моей проблемы с методом SetPropertyValue. Нет способа извлечь из него ValueType. codekaizen
Хорошо, достаточно справедливо ... Я следую до сих пор. Но как это работает? экземпляр вернуться к модели предметной области? codekaizen
dt = компонент, только что приведенный к DateTime. Я мог бы заменить его везде компонентом ((DateTime)). Компонент - это то, что фактически возвращается к модели предметной области.
6

Сделайте тип пользователя неизменяемым, вернув false вIsMutable и просто бросить исключение вSetPropertyValue.

У меня есть нечто похожее, но с собственным типом данных вместоDateTimeOffset, Я просто адаптировал код для вас. Он хранит дату как время UTC, а смещение какTimeSpan (сохраняет галочки. Конечно, вам не нужно это разрешение. Но вы не должны хранить целые часы для часовых поясов, естьtime zones offsets with fractions of hours!! А также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

Похожие вопросы