我想对集合属性进行持久性操作,由我自己决定是否可以与数据库同步,并在确定一次持久性在所有集合上而不是每个元素上都发生持久性时调用一个过程。
怎么做 ?
这些集合属性通常使用一对多或多对多关联进行映射。所以,当我们有这样的事情:
myEntity.List.Add(new Item()); myEntity.List.Add(new Item()); ... session.Save(myEntity);
对于具有两个类(实体)和单向多对多关联的映射,我只希望发生两个sql语句:INSERT INTO和PROCEDURE CALL,期望接收以逗号分隔的值列表,该列表是来自List上面的收藏。键集合只能保存在该系统上,该系统调用带有值列表(csv)的过程。
INSERT INTO
PROCEDURE CALL
List
可以进行这种定制吗?
好吧,我采用了实现NHibernate侦听器的解决方案,所以我有一个像这样的侦听器:
public class CustomSaveUpdateEventListener : IPostInsertEventListener, IPostUpdateEventListener { private void ScheduleToCommit(AbstractPostDatabaseOperationEvent @event) { // Some filter if (@event.Entity.GetType().FullName.Equals(MY_ENTITY_TO_INTERCEPTS) { object o = @event.Entity; // Some logic... // ... // ... IQuery namedQuery = @event.Session.GetNamedSQLQuery(MY_NAMED_QUERY); //namedQuery.SetParameter(...); // <== You can set parameters //namedQuery.ExecuteUpdate(); // <== DO NOT EXCEUTE HERE, this launches more events recursively and can generate stackoverflow @event.Session.ActionQueue.RegisterProcess(new MyActionBeforeCommit(@event, namedQuery).SaveValuesOperation); } } } public void OnPostInsert(PostInsertEvent @event) { ScheduleToCommit(@event); } public void OnPostUpdate(PostUpdateEvent @event) { ScheduleToCommit(@event); } }
而且我的对象MyActionBeforeCommit()被安排为仅在提交事务后才运行。因此,在我的“未来行动”中,我有:
MyActionBeforeCommit()
public class MyActionBeforeCommit { private AbstractPostDatabaseOperationEvent e; private IQuery query; public MyActionBeforeCommit(AbstractPostDatabaseOperationEvent e, IQuery query) { this.e = e; this.query = query; } public void SaveValuesOperation() { // Here your query will be executed only when a transation is commited, if // it's rolledback this won't be executed query.ExecuteUpdate(); } }
最后,我们需要在NHibernate配置上注册新的侦听器,如下所示:
Configuration.SetListener(ListenerType.PostInsert, new CustomSaveUpdateEventListener()); Configuration.SetListener(ListenerType.PostUpdate, new CustomSaveUpdateEventListener());
而且效果很好。这是一个非常好的NHibernate功能,非常强大。