Аудит данных в NHibernate с использованием событий - PullRequest
9 голосов
/ 09 марта 2009

Я вновь и вновь внедряю код, который заставил меня задать этот вопрос об аудите данных в NHibernate. Однако на этот раз я хочу пойти с Шоном Карпентером предложением и реализовать 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.

Ответы [ 3 ]

11 голосов
/ 27 июля 2009

Вы также можете использовать метод 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.
}
6 голосов
/ 09 марта 2009

Я бы не знал, как добиться того, что вы хотите, с помощью интерфейса 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'
        // (...)
    }
}

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

0 голосов
/ 09 марта 2009

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

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