Аудит данных в NHibernate с использованием событий

Я пересматриваю и повторно реализую код, который заставил меня задать этот вопрос про аудит данных в NHibernate. Однако на этот раз я хочу использовать . / questions / 15917 / data-auditing-in-nhibernate-and-sqlserver / 142767 # 142767 "> предложение и реализовать ISaveOrUpdateEventListener (новое в NHibernate 2.x)

Я хочу добавить строку в базу данных для каждого изменения каждого свойства со старым значением и новым, поэтому позже в пользовательском интерфейсе я могу сказать что-то вроде «Пользователь Боб изменил свойство Wibble с A на B 9 марта 2009 года. в 21:04 "

Как лучше всего сравнить состояние объекта, чтобы определить, какие свойства объекта изменились?

Вы можете получить загруженное состояние объекта следующим образом:

    public void OnSaveOrUpdate(SaveOrUpdateEvent saveOrUpdateEvent)
    {
       object[] foo = saveOrUpdateEvent.Entry.LoadedState;
    }

И я полагаю, что мог бы использовать отражение, чтобы определить, какие свойства изменились, но я покопался и не нашел подходящего набора свойств для сравнения. Я бы подумал, что будет метод GetChangedProperties () или что-то в этом роде.

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

В каком направлении лучше всего двигаться?

P.S. Если это имеет значение, это проект архитектуры ASP.NET-MVC / S # arp.


person Iain Holder    schedule 09.03.2009    source источник


Ответы (3)


Я бы не знал, как достичь того, чего вы хотите, с помощью интерфейса ISaveOrUpdateListener - однако вы можете воспользоваться тем фактом, что оба интерфейса IPreUpdateEventListener и IPreInsertEventListener предоставляют то, что вам нужно ... например. сделай что-нибудь вроде этого:

public bool OnPreUpdate(PreUpdateEvent evt)
{
    string[] names = evt.Persister.PropertyNames;
    for(int index = 0; index < names.Length; index++)
    {
        // compare evt.State[index] to evt.OldState[index] and get
        // the name of the changed property from 'names'
        // (...)
    }
}

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

person mookid8000    schedule 09.03.2009
comment
Спасибо за и получите название измененного свойства из "names". Я пробыл в сети 15 минут в поисках надежного способа сопоставления объекта со значениями. - person SamuelKDavis; 18.06.2014

Вы также можете использовать метод FindDirty в Persister, чтобы позволить NHibernate делать сравнения за вас:

var dirtyFieldIndexes = @event.Persister.FindDirty(@event.State, @event.OldState, @event.Entity, @event.Session);

foreach (var dirtyFieldIndex in dirtyFieldIndexes)
{
    var oldValue = @event.OldState[dirtyFieldIndex];
    var newValue = @event.State[dirtyFieldIndex];

    // Log values to new "AuditLog" object and save appropriately.
}
person Darrell Mozingo    schedule 27.07.2009

Вы можете реализовать шаблон Memento для сериализации состояния из начальной загрузки с помощью ILoadEventListener. Очевидно, вы не хотите хранить коллекции / отношения, иначе вы дублируете весь граф объекта. Затем вы можете вытащить это и сравнить в своем ISaveOrUpdateEventListener.

person James L    schedule 09.03.2009