使用EF Code First的DDD - 如何将它们组合在一起?

Cat*_*lin 17 c# asp.net-mvc domain-driven-design code-first ef-code-first

我正在学习DDD开发几天,我开始喜欢它了.

我(我想)了解DDD的原理,其中您主要关注业务对象,其中您有聚合,聚合根,仅用于聚合根的存储库等等.

我正在尝试创建一个简单的项目,我将DDD开发与Code First方法结合起来.

我的问题是:(我使用的是asp.net MVC)

  1. DDD Business Objects将与Code First对象不同?即使它们可能是相同的,例如我可以拥有一个Product具有所有规则和方法的业务对象,并且我可以拥有一个Product代码优先(POCO)对象,它将只包含我需要保存在数据库中的属性.

  2. 如果问题1的答案是"真",那么我如何通知ProductPOCO对象业务对象的属性Product已被更改,我必须更新它?我正在使用"AutoMapper"或类似的东西?如果答案是"不",我就完全迷失了.

你能告诉我一个最简单的(CRUD)例子,我怎么能把这两个放在一起?

谢谢

Jos*_*off 7

更新我不再提倡使用"域对象",而是主张使用基于消息传递的域模型.请看这里的例子.

#1的答案取决于它.在任何企业应用程序中,您将在域中找到2个主要类别的东西:

直CRUD

这里不需要域对象,因为对象的下一个状态不依赖于对象的先前状态.这是所有数据,没有行为.在这种情况下,可以在任何地方使用相同的类(即EF POCO):编辑,持久化,显示.

例如,在订单上保存帐单邮寄地址:

public class BillingAddress {
  public Guid OrderId;
  public string StreetLine1;
  // etc.
}
Run Code Online (Sandbox Code Playgroud)

另一方面,我们......

国家机器

您需要为域行为和状态持久性(以及执行工作的存储库)提供单独的对象.域对象上的公共接口应该几乎总是所有void方法,而不是公共getter.这方面的一个例子是订单状态:

public class Order { // this is the domain object  
  private Guid _id;
  private Status _status;

  // note the behavior here - we throw an exception if it's not a valid state transition
  public void Cancel() {  
    if (_status == Status.Shipped)
      throw new InvalidOperationException("Can't cancel order after shipping.")
    _status = Status.Cancelled;
  }

  // etc...
}

public class Data.Order { // this is the persistence (EF) class
  public Guid Id;
  public Status Status;
}

public interface IOrderRepository {
  // The implementation of this will:
  // 1. Load the EF class if it exists or new it up with the ID if it doesn't
  // 2. Map the domain class to the EF class
  // 3. Save the EF class to the DbContext.
  void Save(Order order); 
}
Run Code Online (Sandbox Code Playgroud)

#2的答案是DbContext将自动跟踪EF类的更改.


kab*_*ros 2

答案是否定的。EF 代码优先的最佳优点之一是它非常适合 DDD,因为您必须手动创建业务对象,因此请使用 EF 模型来等效于 DDD 实体和值对象。无需添加额外的复杂性,我认为 DDD 不建议在任何地方这样做。

您甚至可以让您的实体实现 IEntity,让值对象实现 IValue,另外遵循 DDD 模式的其余部分(即存储库)来与数据库进行实际通信。更多这些想法,您可以在 .NET 中找到这个非常好的示例应用程序,即使它不首先使用 EF 代码,它仍然非常有价值: http: //code.google.com/p/ndddsample/

  • 确实,Code First 允许您创建类而不必担心数据库,但我认为它们不能用域对象替换,域对象有很多私有属性、方法、只读字段,所有这些都可以' t 被 EF 正确映射。这就是为什么我认为你应该有两个对象 (8认同)
  • 您可以拥有您提到的所有内容,并且可以在映射中忽略它们或将它们映射到不同的列名称等...映射是 IRepository 实现的一部分,并成为不会污染您的模型的实现细节。在所有情况下,良好的设计都是关于管理复杂性,因此即使您没有严格遵循 DDD,管理一个业务对象层仍然会更好。如果您有一个要连接的遗留数据库并希望有一个干净的模型,那么您可能需要这样的映射,然后将其映射到与您的数据库匹配的另一个模型 (2认同)