[NHibernate] Automatyczna aktualizacja daty i czasu – o ostatniej zmianie w rekordzie
Jak pisałem poprzednio o problemie braku milisekund w dacie. Wspomniałem o tym, że tabele posiadają kolumnę informującą o ostatniej zmianie, która nastąpiła na rekordzie. Można się domyślić, że ręczne ustawianie tej wartości było by mozolne oraz podatne na błędy ( w szczególności – zapomnienie o wstawieniu nowej wartości)
Można to zautomatyzować przy użyciu Listnera. „Nasłuchiwacza” na zmiany wysyłane do bazy danych.
public class LastChangeListener : IPreUpdateEventListener, IPreInsertEventListener
{
public bool OnPreUpdate(PreUpdateEvent @event)
{
var model = @event.Entity as ILastChange;
if (model == null)
{
return false;
}
var time = DateTime.Now;
Set(@event.Persister, @event.State, "LastChange", time);
model.LastChange = time;
return false;
}
public bool OnPreInsert(PreInsertEvent @event)
{
var model = @event.Entity as ILastChange;
if (model == null)
{
return false;
}
var time = DateTime.Now;
Set(@event.Persister, @event.State, "LastChange", time);
model.LastChange = time;
return false;
}
private void Set(IEntityPersister persister, object[] state, string propertyName, object value)
{
var index = Array.IndexOf(persister.PropertyNames, propertyName);
if (index == -1)
return;
state[index] = value;
}
}
Encje posiadają properties (właściwość) o typie DateTime
o nazwie LastChange
. Do tego te encje implementują interfejs ILastChange
, który wymusza zaimplementowanie property LastChange
.
Aby NHibernate zaczął korzystać z Listnera, trzeba go zarejestrować podczas tworzenia SessionFactory. Jeżeli korzystasz z Fluent NHibernate rejestracja wygląda następująco:
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012
.ConnectionString(c => c.FromAppSetting("ConnectionString")))
.ExposeConfiguration(config =>
{
config.EventListeners.PreUpdateEventListeners = new IPreUpdateEventListener[]
{
new LastChangeListener(),
};
config.EventListeners.PreInsertEventListeners = new IPreInsertEventListener[]
{
new LastChangeListener(),
};
}).BuildSessionFactory();