【问题标题】:NHibernate Cascade Behavior for Same Session Updates相同会话更新的 NHibernate 级联行为
【发布时间】: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


    【解决方案1】:

    NHibernate 文档说,flush 会持久保存与 会话。

    主要问题是断开连接实体和连接实体之间的区别。级联对两者的行为相同,但隐式更新不同。对于会话加载的实体,不需要将保存级联到买方,因为它是多余的。对于断开连接的实体,您需要级联,因为不会对该买方进行隐式更新,因为它从未显式合并到会话中。

    【讨论】:

    • 这也是我阅读文档的方式。只是另一种方法对我来说似乎更有意义,而且我没有看到在同一会话场景中对更新级联的任何明确讨论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多