我有一个对象,我保持对另一个对象的关系:使用临时对象将导致瞬时对象异常
public class Foo {
public Bar Bar { get; set; }
}
在映射我参考吧,以我能保持的关系 - 我不想父对象到子更新属性,只是关系存在:
:References(x => x.Bar, "BarId")
.Cascade.None();
在UI层我使用属性是不是底层主键创建关系
item.Bar = new Bar { Code = "123" };
在存储库层I水合对象,如果没有它的主键填充:
if(item.Bar.Id == null)
{
item.Bar = barRepository.RetrieveByCode(item.Bar.Code);
}
当我RetrieveByCode线延伸(这是一个Criteria.UniqueResult下盖)我得到一个TransientObjectException告诉我“对象引用一个未保存的瞬态实例 - 在冲洗前保存瞬态实例”。
当我运行相同的代码路径而不创建临时Bar对象时,它的工作原理。看起来,作为临时对象创建的Bar被NHibernate追踪,但我希望它忘记它曾经存在,因为它只是一个占位符。
有关如何实现此目的的任何想法?
UPDATE:对此做了一些更多的测试,它似乎是Foo中导致问题的更改跟踪。如果我在检索它之后调用Session.Evict(item),但在进行任何更改之前,然后在完成后使用Session.Update(item)重新附加该对象,似乎可以工作,但是它更新了不是我想要的 - 我只想管理这种关系。
UPDATE 2:我将FlushMode从Auto更改为Commit。它似乎禁用了对该对象的任何临时更改的排队。在进一步研究了NH行为后,似乎Update更像“重新连接”呼叫而不是明确的“立即更新”呼叫。
UPDATE 3:它看起来不断变化FlushMode导致需要几个操作步骤的事务的其他问题。我回到了尝试另一种方法:
if(item.Bar.Id == null)
{
var barCode = item.Bar.Code;
item.Bar = null;
item.Bar = barRepository.RetrieveByCode(barCode);
}
UI层不关心自己如何对象被持久化。它告诉域名服务在Foo和Bar之间建立关系。域服务调用各种存储库来保存适当的对象。 Load示例的挑战是,当它尝试调用Criteria.UniqueResult时,在RetrieveByCode期间抛出了TransientObjectException,所以我将无法进入Load调用。 – 2010-06-22 15:00:37
存储库应该共享一个ISession,以便他们可以参与事务。我不明白为什么标准查询会抛出异常;你可以发布代码吗? – 2010-06-22 17:43:13
它可能会抛出,因为它正在冲洗并发现假Bar对象被引用。如果它是级联的,它会坚持一个新的实例。整个用法是错误的。 – 2010-06-23 00:29:21