查看了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