使用NHibernate驱逐和更新对象会使所有引用无效

时间:2014-02-05 12:42:39

标签: nhibernate

我正在研究一些需要更清晰的NHibernate的意外行为。 我创建一个新对象'Request'并保存它。我创建另一个对象'AuditLog'并添加请求作为对AuditLog的引用。我也保存了。 现在,如果Request对象被逐出会话(由于某种原因)并再次更新,则在提交事务时,AuditLog中的引用在数据库中是NULL化的。

关于为什么会发生这种情况的任何想法?

如果请求对象未在会话中创建,但是从数据库中检索,并且运行相同的进程,则会保留AuditLog中的引用。

为便于理解而编辑的示例代码。 如果我从代码中删除session.Evict(request1),则测试通过。使用此代码,当会话关闭时,会在DB上触发另一个查询,以使AuditLog中的请求引用为空。

//Session 1
var session = Resolve<IFullSession>().Session();
using (var tx = session.BeginTransaction())
{
    var request1 = new Request { Id = "REQ01" };
    request1.SetFieldValue("Type", "Stage1"); //Type is column in Request table
    session.Save("Request", request1);

    var auditLog1 = new AuditLog { Id = "LOG01" };
    auditLog1.SetFieldValue("Request", request1); //Request is reference column to AuditLog
    session.Save("AuditLog", auditLog1);

    session.Evict(request1);
    request1.SetFieldValue("Type", "Stage2");
    session.SaveOrUpdate("Request", request1);

    tx.Commit();
}
CreateInnerContainers(); // This closes earlier session.
//Session 2
var session2 = Resolve<IFullSession>().Session();
using (var tx = session2.BeginTransaction())
{
    var theLogObject = session2.Get<AuditLog>("LOG01");
    Assert.IsNotNull(theLogObject); // This is true
    Assert.IsNotNull(theLogObject.GetFieldValue("Request")); // This fails
    tx.Commit();
}

2 个答案:

答案 0 :(得分:1)

您可以访问会话对象,然后使用您喜欢的任何内容

session.GetSessionImplementation().PersistenceContext.EntityEntries

but if I were you i would make sure that i'm evicting the right object and spend some time on debuging. Knowing what is going on is better than searching for workarounds

foreach (var e in session.GetSessionImplementation().PersistenceContext.EntityEntries.Values.OfType<EntityType>().Where(<condition>))
{
    session.Evict(e);
}

答案 1 :(得分:1)

会话上的Save调用并不意味着您的实体被写入底层数据库。它将在当前持久化上下文(您的会话)中保持不变。

如果您现在从持久性上下文中删除此实体(您使用“evict”执行操作),则您的会话将无法将其保存在flush(事务结束)上。

尝试在session.Evict(request1)之前调用session.Flush(),看看会发生什么。

我不知道NHibernate,我来自hibernate,但最终这有助于澄清。