Отображение неизменной структуры как компонент в NHibernate

Я проверяю NHibernate, чтобы быть решением потребностей ORM моей компании. Чтобы сделать это, я произвел маленькую экспериментальную модель на основе школы, обеспечив некоторые полезные пограничные случаи для NHibernate для обработки.

У меня есть проблемы при обнаружении, как отобразить пользовательскую структуру как компонент объекта, не используяIUserType интерфейс. Я должен подчеркнуть, что это - важное требование, чтобы доменные классы были в отдельном блоке от нашего кода NHibernate, и что доменный блок не имеет ссылки на NHibernate.

Пользовательская структура Time, используемый для представления времени суток в часах и минутах. Это - очень простая неизменная структура и только обеспеченный для иллюстрирования проблемы пользовательской структуры. Конструктор берет отдельный аргумент, который является часами и минутами как целое число в форме hhmm.

public struct Time
{
    public Time(int hoursAndMinutes)
    {
        // Initialize Structure //
    }

    public int Hours { get; private set; }

    public int Minutes { get; private set; }

    public int HoursAndMinutes { get; private set; }
}

Эта структура используется в качестве компонента Lesson класс для хранения времени суток урок запускается:

public class Lesson
{
    public int ID { get; private set; }
    public Teacher Teacher { get; internal set; }
    public DayOfWeek Day { get; set; }
    public Time StartTime { get; set; } // <-- Custom Type
    public int Periods { get; set; }
}

Этот класс отображается непосредственно на эту таблицу:

CREATE TABLE Lessons
(
    ID INT,
    Subject NVARCHAR(128)
    TeacherID INT,
    Day VARCHAR(9),
    StartTime INT, // <-- Maps to custom type.
    Periods INT
)

Я ищу способ отобразить эту структуру как компонент Lesson класс, так, чтобы NHibernate считал значение свойства на структуре (как любой другой компонент) для получения значения для столбца, но инициализировал новый экземпляр структуры путем передачи значения столбца конструктору при чтении значения из столбца в объект.

Если бы у Вас есть какие-либо предложения, это было бы супер. Если Вы хотите сказать мне, который это не может быть выполнено без использования IUserType, это - прекрасный ответ также.

9
задан Paul Turner 31 December 2009 в 11:25
поделиться

2 ответа

Насколько мне известно, существует три плана атаки.

  • Можно отобразить компонент непосредственно в свойства пользовательского типа. В данном примере NHibernate должен установить свойство HoursAndMinutes, изменить код в этом свойстве, чтобы обновить свойства Hours и Minutes соответственно, и заставить конструктор просто вызвать это. HoursAndMinutes = hoursAndMinutes; поэтому тот же самый код для обновления свойств Hours и Minutes выполняется независимо от того, используется ли конструктор или сеттер свойства HoursAndMinutes. Вы бы написали это так, если бы не использовали ORM и знали, что оно будет работать с этим свойством? Скорее всего, нет. Но это не конец света и комментарий всё бы объяснил.

  • Вы пишете реализацию IUserType или ICompositeUserType. На самом деле, они существуют именно для этого сценария и дают Вам гибкость для инстанцирования структуры, как Вам угодно в реализации NullSafeGet(), и извлечения данных, как Вам угодно в реализации NullSafeSet(). Поместите его в другую сборку, скажем MyModel.NHibernateCrap.dll, если хотите. Нет необходимости, чтобы ваша модель/домен знала, что реализация IUserType или NHibernate существует - это все, что нужно указать в файле отображения.

  • Вы используете обходной путь, основанный на коде, описанный Мики Уоттсом в его ответе. То есть, ваш компонент в NHibernate отображает карты полей или частных свойств в вашем типе модели, которые делают какое-то волшебное ручное махание, чтобы преобразовать их в публичные свойства, которые использует приложение, и наоборот. (Это похоже на первый вариант, который я предоставляю; единственное отличие заключается в том, что в его сценарии поле представляет собой обходной путь, который позволяет наследственной базе данных утечь в реализацию класса, но не в другие части приложения или модели. Для небольших, изолированных случаев, или если наследственная БД - это просто Fact of Life, то я думаю, что это вполне разумно)

Чтобы напрямую и реалистично ответить на ваш вопрос, NHibernate не будет вызывать конструктор, у которого есть параметры, period- это просто как он работает, он сообщает новости объекту, а затем начинает устанавливать и размышлять над ним--нет, если вы начнете делать странные вещи с прокси или скажете ему использовать вашу IUserType-реализацию. Нет механизма, чтобы сказать что-то вроде <конструктор>HoursAndMinutes в маппинг-файле или что-то в этом роде. Перестаньте волноваться и полюбите бомбу.

Так как IUserType - это механизм, предоставляемый NHibernate для таких вещей, я не совсем понимаю, почему не хочется его использовать.

Удачи!

16
ответ дан 4 December 2019 в 11:42
поделиться

Я работаю с устаревшей базой данных, основанной на приоритетной ERP. В базе данных время представлено как целое число минут, начиная с эпохи. Так, например, число 0 представляет 01/01/1988 00:00, а число 1440 представляет 02/01/1988 00:00 и так далее.

Решение, которое я был найден за это выглядит так:

    [Field("CURDATE")]
    private int transactionDate = DateTimeHelper.ConvertToInternalValue(DateTime.Today);

    public DateTime TransactionDate
    {
        get { return DateTimeHelper.ConvertToDateValue(transactionDate); }
        set { transactionDate = DateTimeHelper.ConvertToInternalValue(value); }
    }

, где функции на DateTimeHelper делают фактическое преобразование от целочисленного количества минут до фактической структуры DateTime.

2
ответ дан 4 December 2019 в 11:42
поделиться
Другие вопросы по тегам:

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