Как реализовать столбцы ChangeTime и ChangeUser с помощью NHibernate? - PullRequest
14 голосов
/ 16 февраля 2009

Я пытаюсь использовать NHibernate с существующей базой данных. В модели данных есть столбцы в каждой таблице, которые содержат время и имя пользователя последнего обновления строки. Как мне сделать это с помощью NHibernate?

Я попытался реализовать перехватчик, который устанавливает ChangeTime и ChangeUser в объектах, прежде чем он будет сохранен с помощью метода IInterceptor.OnSave. Это не сработало, потому что установка этих свойств вызывает обновление строки, даже если никакие другие свойства не были изменены.

Это могло бы сработать, если бы был какой-то способ сказать NHibernate об исключении свойств ChangeTime и ChangeUser, тогда он выполняет грязную проверку. Но я не нашел способа сделать это.

Спасибо за любую помощь.

Ответы [ 4 ]

14 голосов
/ 16 февраля 2009

Вы должны зарегистрировать слушателя для событий перед вставкой и перед обновлением. Вы можете сделать это через вашу конфигурацию так:

<hibernate-configuration>
    ...
    <event type="pre-update">
        <listener class="MyListener, MyAssembly"/>
    </event>
    <event type="pre-insert">
        <listener class="MyListener, MyAssembly"/>
    </event>
</hibernate-configuration>

, а затем реализовать слушателя - что-то вроде этого (может быть, не совсем точно - списано из моей памяти):

public class MyListener : IPreUpdateEventListener, IPreInsertEventListener
{
    public bool OnPreUpdate(PreUpdateEvent evt)
    {
        if (evt.Entity is IHasLastModified)
            UpdateLastModified(evt.State, evt.Persister.PropertyNames);

        return false;
    }

    public bool OnPreInsert(PreInsertEvent evt)
    {
        if (evt.Entity is IHasLastModified)
            UpdateLastModified(evt.State, evt.Persister.PropertyNames);

        return false;
    }

    void UpdateLastModified(object[] state, string[] names)
    {
        var index = Array.FindIndex(names, n => n == "LastModified");

        state[index] = DateTime.Now;
    }
}

и сделать то же самое с событием перед обновлением.

РЕДАКТИРОВАТЬ: Это заботится о вставке, а также обновления, и, кажется, работает.

5 голосов
/ 30 июня 2009

Эй, мне просто нужно было решить эту проблему в проекте, над которым я работаю, вот мой ответ

public interface IDateModified
{
    DateTime Created { get; set; }
    DateTime Modified { get; set; }
}

public class CustomDefaultSaveOrUpdateEventListener 
    : DefaultSaveOrUpdateEventListener
{
    protected override object EntityIsPersistent(SaveOrUpdateEvent evt)
    {
        var entity = evt.Entity as IDateModified;
        if (entity != null)
        {
                entity.Modified = DateTime.Now;
        }

        return base.EntityIsPersistent(evt);
    }

    protected override object EntityIsTransient(SaveOrUpdateEvent evt)
    {
        var entity = evt.Entity as IDateModified;
        if (entity != null)
        {
            entity.Created = entity.Modified = DateTime.Now;
        }

        return base.EntityIsTransient(evt);
    }
}

Затем в моей конфигурации (я использую Fluent NHibernate для настройки своих модульных тестов в коде)

configuration.EventListeners.SaveOrUpdateEventListeners 
= new ISaveOrUpdateEventListener[]
{
    new CustomDefaultSaveOrUpdateEventListener() 
};

AWESOMENESSSSSSSS!

1 голос
/ 14 июня 2009

Ответ Mookid верный, хотя я хотел бы отметить, что если используется архитектура S # arp, конфигурация NHib должна быть настроена следующим образом:

<hibernate-configuration>
    <session-factory>
    ...
        <event type="pre-update">
            <listener class="MyListener, MyAssembly"/>
        </event>
        <event type="pre-insert">
            <listener class="MyListener, MyAssembly"/>
        </event>
    </session-factory>
</hibernate-configuration>

Элементы события входят в элемент session-factory.

0 голосов
/ 30 июня 2009

Вместо использования LIsteners вы также можете использовать Interceptors: Аудит изменений с использованием перехватчика

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...