我有一个双层(非网络)系统,我将把一些对象加载到系统内存中,偶尔将它们刷回数据库。让我们假设我只需要更新一个对象,但该对象是一个包含数百个实体的相当大的图形,我使用级联来使保存传播到整个图形。
当在第二个会话中调用Session.Update(the_big_object)时,NHibernate“正确”将整个对象图中的每个实体覆盖到数据库,创建大量更新,即使它们未被更改。这是可以理解的,因为它不知道在会话之外发生了什么变化。使用Session.Merge(the_big_object)并没有多大帮助,因为它也需要大量的查询。
问题在于我的情况,通常大图中只有少数几个实体发生了变化。我在想的是,不是使用级联来保存整个对象,也许将脏实体集合保存在内存中是个好主意,并且只在需要时清除它们。为此,我可能需要向绑定到其setter的类添加脏标志等等。
然后我想,是不是NHibernate在会话中做了什么,以确定哪些对象是脏的?所有这些代理/版本的东西都适用于持久对象,但不适用于分离的对象(或者它们是什么?)。我觉得有点愚蠢需要再次手工完成。
我可以采取任何建议/方法,还是有任何我不知道的魔术?
非常感谢!
答案 0 :(得分:2)
除非您自己手动跟踪已更改的实体,否则看起来没有办法执行您要求的操作。看看这篇文章。它与您的要求类似:
What is the best approach to update only changed properties in NHibernate when session detached?
在进行更新之前,您可以将对象重新连接到会话吗?如果是这样,你可以这样做:
using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction())
{
var p = new Person {PersonId = 1};
session.Lock(p, LockMode.None); // <-- This is the secret sauce!
p.Firstname = "Bob";
// No need to call session.Update(p) since p is already associated with the session.
tx.Commit();
}
答案 1 :(得分:0)
一些未经考验的想法:
使用查询或访问任何延迟加载的集合,在第二个会话中加载整个对象图。然后将分离的对象合并到第二个会话中;这不应该需要任何其他查询,因为整个对象图将位于缓存中。
在对象中实现INotifyPropertyChanged并跟踪顶级对象中的脏对象。如果图表中有许多不同的类型,这是相当多的工作。
另一个选项可能是序列化原始会话并在准备好刷新会话时反序列化。您应该能够将实体合并回原始会话,而无需额外的数据库访问。
答案 2 :(得分:0)
只是想知道:
考虑将原始对象存储在内存中(例如,针对Web应用程序的Session),并在更新的对象返回时查找更改集(例如,在回发中)。
我正在寻找一种方法将deattached对象附加到会话而不查询DB。