我有一个对象,我与另一个对象保持关系:
public class Foo {
public Bar Bar { get; set; }
}
在映射中我引用了Bar,我可以维护关系 - 我不希望父对象更新子进程中的属性,只是存在关系:
References(x => x.Bar, "BarId")
.Cascade.None();
在UI层中,我使用不是基础主键的属性创建关系:
item.Bar = new Bar { Code = "123" };
在存储库层中,如果对象没有填充主键,则会对其进行水合:
if(item.Bar.Id == null)
{
item.Bar = barRepository.RetrieveByCode(item.Bar.Code);
}
当我运行RetrieveByCode行(这是一个Criteria.UniqueResult)时,我得到一个TransientObjectException告诉我“对象引用一个未保存的瞬态实例 - 在刷新之前保存瞬态实例”为Bar类型。
当我运行相同的代码路径而不创建临时Bar对象时,它可以工作。似乎作为临时对象创建的Bar由NHibernate跟踪,但我希望它忘记它曾经存在,因为它只是一个占位符。
有关如何实现这一目标的任何想法?
更新:对此进行更多测试似乎是Foo中的更改跟踪导致了问题。如果我在检索后调用Session.Evict(item),但在进行任何更改之前使用Session.Update(item)重新附加对象后,它似乎工作,但它会更新不是的子对象我想要什么 - 我只想管理这段关系。
更新2 :我将FlushMode从Auto更改为Commit。它似乎已禁用对象的任何临时更改的排队。进一步研究NH行为后,似乎Update更像是“重新连接”调用,而不是明确的“立即更新”调用。
更新3 :看来更改FlushMode会导致需要多个操作步骤的事务的其他问题。我回过头来尝试另一种方法:
if(item.Bar.Id == null)
{
var barCode = item.Bar.Code;
item.Bar = null;
item.Bar = barRepository.RetrieveByCode(barCode);
}
答案 0 :(得分:0)
为什么你希望它以这种方式工作?为什么不使用检索到的Bar对象简单地设置item.Bar:
item.Bar = barRepository.RetrieveByCode("123");
您可以使用Load
:
if(item.Bar.Id == null)
{
var bar = barRepository.RetrieveByCode(item.Bar.Code);
item.Bar = session.Load<Bar>(bar.Id);
}