NHibernate级联设置的文档,讨论调用Save()Update()和Delete()方法的上下文中的设置。但是,当在同一会话上加载,修改和保存实体时发生的隐式更新的上下文中,我找不到关于级联行为的讨论。在这种情况下,不需要显式调用更新,那么级联设置会发生什么?
这似乎是一个愚蠢的问题,但我提出这个问题的原因是我试图弄清楚NHibernate如何在域驱动设计的上下文中支持聚合边界的概念。让我举一个例子来说明我想要达到的目标。
假设我有实体发票应用程序,包含Invoice,Buyer和LineItem实体。 Invoice是聚合根,LineItem在同一聚合中,但Buyer是其自己的聚合根。
我想在NHibernate中通过配置我的映射来建模,以便从Invoice到LineItem的级联是All-DeleteOrphans
,而从Invoice到Buyer的级联是None
。
根据我阅读的文档,使用我想要的级联设置,如果我正在使用断开连接的实体,并且我执行以下操作,则只有Invoice和LineItems将保存:
disconnectedInvoice.ShippedDate = DateTime.Today();
disconnectedInvoice.LineItems[2].Backordered = true;
disconnectedInvoice.Buyer.Address = buyersNewAddress;
session.Update(disconnectedInvoice);
session.Flush();
我在任何地方都没有看到的是当检索发票,进行相同更新并以连接方式刷新会话时会发生什么。
var invoice = session.Get<Invoice>(invoiceNumber);
invoice.ShippedDate = DateTime.Today();
invoice.LineItems[2].Backordered = true;
invoice.Buyer.Address = buyersNewAddress;
session.Flush();
NHibernate文档说,flush会持久保存与会话关联的脏实体的更改。基于此,我们假设对Invoice,Buyer和LineItems的更新都将被保留。
但是,这似乎违反了级联规则背后的概念。在我看来,为了决定在刷新时更新哪些实体,会话应该查看那些直接加载的实体(在这种情况下只有发票)并包括间接加载的实体(LineItems和买方在此case)仅当级联设置表明它们应该被保留时。
我承认这个例子代表了糟糕的DDD。如果买方不是汇总的一部分,则此时不应更新。或者至少它不应该通过Invoice汇总进行更新。但是,除了DDD之外,我实际上更感兴趣的一点是确定级联规则是否适用于同一会话场景中的更新,与在断开连接的场景中相同。
答案 0 :(得分:1)
NHibernate文档说,flush会持久保存与之关联的脏实体的更改 会话。
主要问题是断开连接和连接实体之间的区别。级联对两者的行为都相同,但它是不同的隐式更新。对于会话加载的实体,不需要将保存级联到买方,因为它是多余的。对于断开连接的实体,您需要级联,因为该买方没有隐式更新,因为它从未明确合并到会话中。