【发布时间】:2011-08-12 19:51:19
【问题描述】:
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 不谈,我实际上更感兴趣的一点是,确定在相同会话场景中的更新是否遵循级联规则,就像在断开连接的场景中一样。
【问题讨论】:
标签: nhibernate domain-driven-design cascade