NHibernate i audyt encji

Podczas pisania aplikacji bazodanowych często jest potrzeba zapisywania informacji na temat audytu danej encji. Tylko jak zrobić żeby się nie narobić :). W NHibernate które ostatnio zacząłem używać jest bardzo fajny i wygodny sposób na to. Jak wiemy ten system ORM posiada funkcjonalność jak zdarzanie które są odpalane w różnych momentach np przed zapisem, utworzeniem, kasowaniem itd.
Tworzymy więc sobie interfejs który będzie miał zadeklarowane właściwości opisujące audyt np.

public interface IAuditObject
{
DateTime CreatedDateTime { get; set; }

int CreatedUserId { get; set; }

DateTime ModifyDateTime { get; set; }

int ModifyUserId { get; set; }
}

Teraz wyposażamy klasę naszej encji w ten interfejs. Oczywiście trzeba uzupełnić pliki mapowania o te informacje.
Do przeprowadzenia audytu wykorzystamy dwa zdarzenia które są dostępne: IPreInsertEventListener oraz IPreUpdateEventListener. Te zdarzenia są wywoływane przed dodaniem/zapisem encji. Omówimy teraz sposób implementacji IPreInsertEventListener bo te drugie zdarzenie będzie praktycznie wyglądało bardzo podobnie a różnica będzie w postaci mniejszej ilości pól do zmienienia. A więc jej implementacja mogła by wyglądać następująco:

public bool OnPreInsert(PreInsertEvent @event)
{
if (UpdateAuditInformation(@event.Entity))
{
var entity = @event.Entity as IAuditObject;

Set(@event.Persister, @event.State, "CreatedDateTime", entity.CreatedDateTime);
Set(@event.Persister, @event.State, "ModifyDateTime", entity.ModifyDateTime);
Set(@event.Persister, @event.State, "CreatedUserId", entity.CreatedUserId);
Set(@event.Persister, @event.State, "ModifyUserId", entity.ModifyUserId);
}
return false;
}

W klasie PreInsertEvent są m.in następujące rzeczy:
- instancja naszej encji na której dokonujemy wpisu audytu @event.Entity
- instancja klasy mapującej i zapisującej naszą encje @event.Persister
- tablica wartości które zostaną dodane/zapisane do bazy @event.State
.

Teraz musimy ustawić informacje na temat audytu w naszej encji oraz tablicy stanów. Aby rozpoznać co gdzie leży w tej tablicy możemy skorzystać z obiektu Persister i jego właściwości PropertyNames.
Przykładowa implementacja metody pomocniczej to:

private static void Set(IEntityPersister persister, object[] state, string propertyName, object value)
{
var index = Array.IndexOf(persister.PropertyNames, propertyName);
if (index != -1)
{
state[index] = value;
}
}


Metoda UpdateAuditInformation ustawia nam na encji odpowiednie wartości czasu utworzenia/modyfikacji oraz np ID użytkownika który
wykonał operacje.
Zostaje nam tylko teraz powiadomienie NHibernate o naszej obsłudze tych zdarzeń a możemy to zrobić np:

...
var configuration = new Configuration();
configuration.Configure();

var auditor = new DatabaseAuditor();
configuration.SetListener(ListenerType.PreInsert, auditor);
configuration.SetListener(ListenerType.PreUpdate, auditor);

_sessionFactory = configuration.BuildSessionFactory();
...

0 komentarze:

Prześlij komentarz