C# DDD值对象:如何在没有大量SQL连接的情况下持久化实体对象?

C# DDD值对象:如何在没有大量SQL连接的情况下持久化实体对象?,c#,sql-server,ssis,domain-driven-design,object-persistence,C#,Sql Server,Ssis,Domain Driven Design,Object Persistence,显然,我说DDD在实用性上类似于EAV/CR是错误的,但到目前为止,我看到的唯一区别是为每个实体构建具有大量联接的物理表,而不是三个表和大量联接 这一定是因为我对DDD缺乏了解导入数据时,如何将这些对象以物理方式存储到数据库中,而不会产生明显的连接和复杂性?我知道您可以简单地创建对象,将其输入到存储库中,但很难训练Microsoft Sql Server Integration Server等工具使用自定义C#对象和框架。也许这应该是我的问题,您如何将DDD ASP.NET C#框架与Micro

显然,我说DDD在实用性上类似于EAV/CR是错误的,但到目前为止,我看到的唯一区别是为每个实体构建具有大量联接的物理表,而不是三个表和大量联接

这一定是因为我对DDD缺乏了解导入数据时,如何将这些对象以物理方式存储到数据库中,而不会产生明显的连接和复杂性?我知道您可以简单地创建对象,将其输入到存储库中,但很难训练Microsoft Sql Server Integration Server等工具使用自定义C#对象和框架。也许这应该是我的问题,您如何将DDD ASP.NET C#框架与Microsoft SQL Server集成服务和报表服务结合使用?哈哈

在EAV/CR数据库中,我们可以根据人员类型设置具有不同类别的单人表:供应商、客户、买方、代表、公司、看门人等。插入前,三个表、几个连接、属性始终是带验证的字符串,就像MVC中的ModelValidation一样,对象接受任何值,但在有效之前不会持久

在标准关系模型中,我们为每种类型的实体创建一个表,混合冗余数据类型,如City

使用域驱动设计,我们使用对象来表示每种类型的实体、每种类型的ValueObject的嵌套对象,以及根据需要更多的嵌套对象。在我的理解中,这会导致为每种实体生成一个表,为每种信息集(值对象)生成一个表。在所有这些表中,我看到了很多连接。我们还为每种新的联系人类型创建了一个物理表。显然有更好的方法,所以我在如何将对象持久化到数据库方面肯定是错误的

我的供应商如下所示:

public class Vendor {
    public int vendorID {get; set;}
    public Address vAddress {get; set;}
    public Representative vRep {get;set;}
    public Buyer vBuyer {get; set;}
}
我的买家:

public class Buyer {
   public int buyerID {get; set;}
   public Address bAddress {get; set;}
   public Email bEmail {get; set;}
   public Phone bPhone {get; set;}
   public Phone bFax (get; set;}
}

我们真的参考了Vendor.vBuyer.bPhone.pAreaCode这样的东西吗?我认为我们应该引用并存储Vendor.BuyerPhoneNumber,并构建对象,就像这些部分的别名一样:Vendor.Address1、Vendor.Address2、Vendor.BuyerPhoneNumber。。。等等。

您可以将对象序列化为xml,并将其保存到Sql Server中的xml列中。毕竟,您正试图表示分层数据结构,而这正是xml的优势所在。

领域驱动设计的支持者通常建议将数据模型尽量靠近对象模型,但这不是一条铁一般的规则

如果在对象关系映射层中创建映射,则仍然可以使用将数据转换(投影)到对象中


决定如何设计对象并提供对子值的访问实际上是一个单独的问题,您必须逐个解决<代码>Vendor.BuyerPhoneNumber或
Vendor.vBuyer.bPhone.pAreaCode
?答案总是取决于您的具体需求,因为它植根于您的特定需求。

真正的答案是将您的SQL规范化策略与您的对象相匹配。如果有很多重复的地址,并且需要将它们关联在一起,则将数据规范化为单独的表,从而创建对值对象的需求。

存储域对象的最佳方法之一实际上是文档数据库。它工作得很好,因为文档的事务边界与聚合根的一致性边界完全匹配。您不必担心连接或急切/延迟加载问题。但是,如果您应用CQR(我在下面写过)的话,这并不是绝对必要的

缺点通常是查询。如果您希望直接查询域对象后面的持久化数据,那么您可能会遇到麻烦。然而,这是CQRS旨在为您解决的一个复杂问题,您的应用程序中有不同的部分执行查询,而不是加载/验证/存储域对象

您可能有一个复杂的“命令”实现,它加载域对象,调用域对象上的行为(记住域对象必须有行为并封装其数据,否则可能会变得“贫乏”),然后再保存它们,甚至可以选择发布关于所发生事件的事件

然后,您可以使用这些事件来更新其他一些“读取存储”,尽管您不必这样做。关键是在应用程序中实现了一个完全不同的垂直切片,它不需要处理复杂的对象模型/ORM业务,而是直接进入数据,加载它所需的内容并返回给用户显示

CQR并不难,也不复杂。它所做的只是指示您为以下各项设置单独的代码:

  • 处理命令(改变状态,因此需要涉及的业务规则/不变量)
  • 执行查询(不改变状态,因此不需要所有复杂的业务规则/不变量),因此可以“直接”以高效的方式获取数据