查看了NHibernate.Envers
代碼後,我意識到我實現了錯誤的界面。現在我知道使用什麼界面的工作會更好一些。爲什麼`PreCollectionUpdateEvent`不能插入修改後的集合?
我當前的實現看起來是這樣的:
public class PreCollectionUpdate : IPreCollectionUpdateEventListener
{
public void OnPreUpdateCollection(PreCollectionUpdateEvent @event)
{
var collectionEntry = @event.Session.PersistenceContext.GetCollectionEntry(@event.Collection);
if(!collectionEntry.LoadedPersister.IsInverse)
return;
var collection = @event.Collection;
var collectionEntries = collection.Entries(collectionEntry.LoadedPersister);
foreach(var entry in collectionEntries)
{
if(!(entry is TrackableEntity))
return;
var trackableEntity = entry as TrackableEntity;
trackableEntity.AddedAt = Time.Now;
trackableEntity.AddedBy = User.Current;
}
}
}
通過調試,我可以看到它被稱爲妥善修改我的收藏。但是,由於某些原因,它首先將項目插入我的收藏夾中,並使用AddedAt
和AddedBy
的默認值,然後稍後執行更新以填充所述值。
這裏是我的測試代碼:
using (var transaction = Session.BeginTransaction())
{
var locate = new Locate
{
TicketNumber = 123456789,
Status = Status.InProgress
};
Session.Save(locate);
transaction.Commit();
}
using (var transaction = Session.BeginTransaction())
{
var locate1 = Session.Get<Locate>(1);
locate1.AddReview(new AllClear());
Session.Save(locate1);
transaction.Commit();
}
using (var transaction = Session.BeginTransaction())
{
var locate1 = Session.Load<Locate>(1);
transaction.Commit();
}
這是爲什麼?
調試我的測試我可以看到,在提交我的事務後,AddedBy
和AddedWhen
屬性都被正確填充。只是不確定爲什麼它沒有提交修改後的集合。
在我的代碼中添加一堆Console.Write
聲明我可以看到我的事件偵聽器在之後被調用我提交了會話。
NHibernate: INSERT INTO Locates (AddedAt, AddedBy, TicketNumber, Status, SomeOtherField) VALUES (@p0, @p1, @p2, @p3, @p4); select last_insert_rowid();@p0 = 1/1/0001 00:00:00 [Type: DateTime (0)], @p1 = NULL [Type: String (0)], @p2 = 123456789 [Type: Int64 (0)], @p3 = 'InProgress' [Type: String (0)], @p4 = NULL [Type: String (0)]
Saving review...
Commiting...
NHibernate: INSERT INTO "Review" (AddedAt, AddedBy, Locate_id) VALUES (@p0, @p1, @p2); select last_insert_rowid();@p0 = 1/1/0001 00:00:00 [Type: DateTime (0)], @p1 = NULL [Type: String (0)], @p2 = NULL [Type: Int32 (0)]
In event listener...
Completed filling auditable properties.
我也從IFlushEntityEventListener
試圖inheritign但同樣的問題發生。我承諾沒有AddedAt
和AddedBy
屬性被持久化到數據庫。然而,我的對象會改變,所以下次我使用這個對象時,NHibernate會看到它很髒,並向數據庫發出更新命令。我想要的是在初始提交時提交AddedAt
和AddedBy
屬性。
如果我不清楚,請讓我知道。
我對這種方法不喜歡的是,你需要爲'AddedBy'和'AddedAt'作爲'OnSaveOrUpdate'(這是NHibernate在嘗試保存null或瞬態值時拋出一個異常的地方)運行的允許值在'OnPreInsert'之前。 – Nosila 2012-02-03 16:21:42
@Nosila,這是一個很好的觀點,但是你不能通過在構造函數中初始化TrackableEntity的字段(爲了保存)和更新它們已經有的值來解決這個問題錯誤的值直到鉤子運行)。我知道它很髒。我在當前項目中實際做的另一個選擇是使用IInterceptor,並在事務級別實際創建您的審計日誌。無論如何,這往往對用戶更有用。然後,您可以將整個事務保存到某種審計日誌中。 – acarasso 2012-02-03 17:12:01
@acarasso:這是你正在考慮的文章:http://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener – DanP 2012-02-03 19:48:29