NHibernate автоматически устанавливает свойства при сохранении

Я использую DDD и NHibernate для сохранения объекта домена. В моей базе данных каждая таблица, относящаяся к сущности, имеет четыре дополнительных столбца (CreatedBy, UpdateBy, CreatedDate, UpdDate), используемые для отслеживания аудита. Я использую шаблон репозитория, который позволяет сохранить только совокупные корни. Когда NHibernate пытается сохранить сущности в агрегированном корне, я получаю ошибку SQL DateTime, потому что объекты не имеют своих свойств аудита. Есть ли способ в NHibernate установить свойства объектов непосредственно перед сохранением?

Вот небольшой пример. У меня есть объект Order, который является совокупным корнем. У меня также есть объекты OrderNote, которые являются дочерними элементами порядка. Когда я добавляю OrderNote в Order, а затем сохраняю Order, генерируется исключение, потому что для параметра CreateDate/UpdateDate установлено значение DateTime.MinValue, которое вызовет переполнение SQL DateTime. Поскольку эти столбцы аудита являются частью сохранения и не связаны с проблемным доменом, я не хочу, чтобы root агрегата Order устанавливал эти свойства при добавлении примечания. Столбцы/свойства аудита должны быть известны только инфраструктурой персистентности, а не доменом. Я бы хотел, чтобы NHibernate мог установить эти свойства при сохранении или обновлении. Есть ли способ сделать это?

Ответ 1

Перехватчики могут сделать это:

http://www.nhforge.org/doc/nh/en/index.html#manipulatingdata-interceptors (9.10, ссылка не всегда работает).

Вырезать/вставить из документа:

public class AuditInterceptor : IInterceptor
{
    ...

    public boolean OnSave(object entity,
                          object id,
                          object[] state,
                          string[] propertyNames,
                          IType[] types)
    {
        if ( entity is IAuditable )
        {
            for ( int i=0; i<propertyNames.Length; i++ )
            {
                if ( "CreateTimestamp" == propertyNames[i] )
                {
                    state[i] = DateTime.Now;
                    return true;
                }
            }
        }
        return false;
    }

}

OnFlushDirty() может использоваться для UpdDate.

Вам понадобится всякая сущность, которая имеет CreateDate/UpdateDate для реализации интерфейса, чтобы перехватчик мог проверить, должен ли он действовать (в приведенном примере это IAuditable).


Изменить

Только что заметил главу 11: Перехватчики и события. Вы можете наследовать от EmptyInterceptor, что упрощает работу, если вам нужно только переопределить некоторые из методов.

Я никогда не использовал Events.

Ответ 2

Вы также можете посмотреть систему управления версиями NHibernate, которая может помочь вам в вашем случае;)