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个更多的查询。任何人都知道为什么会这样吗?
答案 0 :(得分:0)
如果在提交交易之前检查_session.IsDirty()
,我的赌注是它将返回true。提交事务时,会刷新会话,并且由于某种原因,加载子对象以级联更改。
这是一个被称为“鬼影”或幻像更新的问题。典型的情况是数据库列是可空的int,但相应的对象属性是不可为空的。当检索到具有空值的记录时,NHibernate将属性值设置为0,因此该对象是脏的。
解决此问题的最快方法是使用XML映射中的dynamic-update="true"
打开对象的动态更新,使用流畅的DynamicUpdate()
,并使用分析器或日志记录查看要更新的列选择之后。还有一个名为Ghostbuster的实用程序,您可以将其包含在单元测试中。