ORM(NHibernate)、DDD和保存复杂实体

ORM(NHibernate)、DDD和保存复杂实体,nhibernate,domain-driven-design,Nhibernate,Domain Driven Design,我是NHibernate的新手(坦率地说是DDD概念),所以我的问题可能很简单,也可能不相关,但如果有人帮我解决困惑,我会非常感激 在我的应用程序中,我使用DDD和NHibernate作为ORM 对于简单的实体,它工作得很好,但现在我的实体变得非常复杂(因此实体a包含实体B和实体C的数组;每个实体C包含D和很少的其他参数等等) 我的客户端应用程序通过互联网与WCF服务(即与db对话)进行对话,因此速度(和有效负载大小非常重要)。在少数情况下,我必须将这些复杂DTO的数组从服务发送到客户机,然后客

我是NHibernate的新手(坦率地说是DDD概念),所以我的问题可能很简单,也可能不相关,但如果有人帮我解决困惑,我会非常感激

在我的应用程序中,我使用DDD和NHibernate作为ORM

对于简单的实体,它工作得很好,但现在我的实体变得非常复杂(因此实体a包含实体B和实体C的数组;每个实体C包含D和很少的其他参数等等)

我的客户端应用程序通过互联网与WCF服务(即与db对话)进行对话,因此速度(和有效负载大小非常重要)。在少数情况下,我必须将这些复杂DTO的数组从服务发送到客户机,然后客户机更新A中的几个值,并将其发送回服务器进行保存/更新

为了减少有效负载,我正在尝试从DTO中的B和C实体中删除未使用的属性值,方法是在将数据从服务发送到客户端时,在映射器中使它们为空(我没有使用automapper等)

现在,当涉及到将实体保存回db时,我应该怎么做?如果我传回实体A,在B和C的几个变量中有空值(我在mapper中手动将其置为空),那么当我保存A时,NHibernate也会尝试保存B和C。我只想保存A,并要求NHibernate不要保存B或C中的任何内容

任何帮助,都将是我的祝福

提前感谢,,
在这种情况下,可以在投影图中找到解决方案。简言之:

  • 保持映射正确且复杂
  • 但在选择数据时,只将需要的列放入
    select
    子句中
这可以通过投影来实现。这里有详细的解释:

文件:


当数据返回到服务器上时,完全映射的实体将能够持久化所有属性。

这种情况下的解决方案可以在projections中找到。简言之:

  • 保持映射正确且复杂
  • 但在选择数据时,只将需要的列放入
    select
    子句中
这可以通过投影来实现。这里有详细的解释:

文件:


当数据返回服务器时,完全映射的实体将能够持久化所有属性。

一旦实体变得复杂,最好将调用实体行为的命令概念与实体本身的结构分离。(本例中的命令是指代表执行操作请求的DTO)。您可以使用如下所示的命令:

class DoSomethingToAnEntityCommand
{
  public string EntityId { get; set; }
  public int SomeValue { get; set; }
}
当应用程序服务处理此命令时,它将加载所需的实体,并调用该实体上的适用行为和提交事务

下一步是将查询与命令解耦。从数据库中检索实体以作为DTO返回时,不必使用与加载实体时相同的检索机制。正如您所指出的,即使对于单个实体,查询需求也可能有所不同。有些查询只需要实体的一部分,加载整个实体的成本可能太高。有多种方法可以仅加载实体的一部分。如Radim Köhler所述,可以使用NHibernate投影。另一种选择是直接使用SQL查询,在NHibernate之外。无论使用哪一种选项,返回的对象都不打算被持久化回来——它们只用于满足查询需求


当需要调用实体上的行为时,不需要传递表示该实体的整个对象图。您只需要传递适当实体的ID以及执行给定操作所需的任何参数,如代码示例中所示。这就是NHibernate的用武之地——它可以按ID加载实体,并跟踪在操作过程中所做的任何更改,以便持久化回数据库。

一旦实体变得复杂,最好将调用实体行为的命令的概念与实体本身的结构分离。(本例中的命令是指代表执行操作请求的DTO)。您可以使用如下所示的命令:

class DoSomethingToAnEntityCommand
{
  public string EntityId { get; set; }
  public int SomeValue { get; set; }
}
当应用程序服务处理此命令时,它将加载所需的实体,并调用该实体上的适用行为和提交事务

下一步是将查询与命令解耦。从数据库中检索实体以作为DTO返回时,不必使用与加载实体时相同的检索机制。正如您所指出的,即使对于单个实体,查询需求也可能有所不同。有些查询只需要实体的一部分,加载整个实体的成本可能太高。有多种方法可以仅加载实体的一部分。如Radim Köhler所述,可以使用NHibernate投影。另一种选择是直接使用SQL查询,在NHibernate之外。无论使用哪一种选项,返回的对象都不打算被持久化回来——它们只用于满足查询需求


当需要调用实体上的行为时,不需要传递表示该实体的整个对象图。您只需要传递适当实体的ID以及执行给定操作所需的任何参数,如代码示例中所示。这就是NHibernate的用武之地——它可以按ID加载实体,并跟踪操作过程中所做的任何更改,以保留到数据库中。

非常感谢Radim的解释。非常感谢Radim的解释。感谢Lev的解释。不幸的是,我无法将两个答案标记为已接受。再次感谢。谢谢你的解释。不幸的是,我无法将两个答案标记为已接受。再次感谢。