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

时间:2012-11-04 12:47:23

标签: c# asp.net-mvc ef-code-first domain-driven-design code-first

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

我(我想)理解DDD的原理,你的主要关注点是业务对象,你有聚合,聚合根,聚合根源的存储库等等。

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

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

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

  2. 如果对问题1的回答为“true”,那么如何通知Product POCO对象业务对象Product中的属性已更改且我必须更新它?我正在使用“AutoMapper”或类似的东西? 如果答案是“不”,我就完全迷失了。

  3. 你能告诉我如何将这两者放在一起的最简单(CRUD)的例子吗?

    谢谢

5 个答案:

答案 0 :(得分:7)

更新我不再提倡使用“域对象”,而是主张使用基于消息传递的域模型。有关示例,请参阅here

#1的答案是取决于。在任何企业应用程序中,您将在域中找到两大类东西:

直接CRUD

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

此示例是在订单上保存帐单邮寄地址:

public class BillingAddress {
  public Guid OrderId;
  public string StreetLine1;
  // etc.
}

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

状态机

您需要具有用于域行为和状态持久性的单独对象(以及用于执行工作的存储库)。域对象上的公共接口应该几乎总是所有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); 
}

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

答案 1 :(得分:2)

最近我做了类似的项目。我正在学习本教程:link 我这样做了:我创建了Blank解决方案,添加了项目:Domain,Service和WebUI。

简单地说在域中我放了模型(例如EF代码的类,方法等) 服务用于域使用asp.net webapi与世界(WebUI,MobileUI,其他站点等)进行通信 WebUi实际上是MVC应用程序(但模型在域中,因此它主要是VC)

希望我帮助

答案 2 :(得分:1)

Pluralsight课程:Entity Framework in the Enterprise进入了与EF Code First合并的域驱动设计的确切场景。

对于1号,我相信你可以这样做。这只是一种风格问题。 对于2号,视频中的讲师会通过几种方式来解释这一点。一种方法是在修改值时在客户端设置的每个类上都有一个“State”属性。然后,DbContext知道要保留的更改。

答案 3 :(得分:1)

答案是否定的。首先,EF代码最好的一点就是它非常适合DDD,因为你必须手动创建业务对象,所以要使用你的EF模型等同于DDD实体和值对象。无需添加额外的复杂层,我不认为DDD会在任何地方推荐。

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

答案 4 :(得分:0)

关于这个主题的晚期问题。 阅读Josh Kodroff的回答证实了我对存储库实现的想法,例如Entity Framework DAL。

您将域对象映射到EF persistance对象,并在保存时让EF处理它。 检索时,让EF从数据库中获取并将其映射到您的域对象(聚合根)并将其添加到您的集合中。

这是存储库实施的正确策略吗?