在提交事务时获取多个查询,为什么?

时间:2010-09-04 14:08:49

标签: nhibernate fluent-nhibernate

public Parent GetByName(string Name)
{
    return _session.CreateCriteria<Parent>()
        .Add(Restrictions.Eq("Name", Name))
        .SetFetchMode("Children", FetchMode.Eager)
        .SetResultTransformer(new DistinctRootEntityResultTransformer())
        .UniqueResult<Parent>();
}

public ParentDetailVM GetMeAParent(string Name)
{
    Parent parent;
    using (var tx = _session.BeginTransaction())
    {
        //This works well, one single query loading
        //both parent and children
        parent = _parentRepository.GetByName(Name);

        //If I include this as suggested by NHProfiler
        //it all of the sudden sends a new query for each child
        //and a query for the grandchildren collection
        tx.Commit();
    }

    return Mapper.Map<Parent, ParentDetailVM>(parent);
}

我已经检查过以确保映射文件中没有任何内容设置为预先加载。如果我不通过事务提交,我无法弄清楚它为什么会起作用,否则会发出N个更多的查询。任何人都知道为什么会这样吗?

1 个答案:

答案 0 :(得分:0)

如果在提交交易之前检查_session.IsDirty(),我的赌注是它将返回true。提交事务时,会刷新会话,并且由于某种原因,加载子对象以级联更改。

这是一个被称为“鬼影”或幻像更新的问题。典型的情况是数据库列是可空的int,但相应的对象属性是不可为空的。当检索到具有空值的记录时,NHibernate将属性值设置为0,因此该对象是脏的。

解决此问题的最快方法是使用XML映射中的dynamic-update="true"打开对象的动态更新,使用流畅的DynamicUpdate(),并使用分析器或日志记录查看要更新的列选择之后。还有一个名为Ghostbuster的实用程序,您可以将其包含在单元测试中。