如何将领域类与EF代码第一层分离并在项目中实现DDD

Posted

技术标签:

【中文标题】如何将领域类与EF代码第一层分离并在项目中实现DDD【英文标题】:How to separate domain classes from EF code first layer and implement DDD in project 【发布时间】:2017-03-14 10:29:27 【问题描述】:

我正在尝试首先使用 EF 代码来控制 DDD。我看到人们首先使用 EF 代码,然后域类驻留在相同的类中。看一个小例子。

   public class TestDBContext : DbContext
    
        public TestDBContext()
            : base("name=TestDBContext")
        
        

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        
            //modelBuilder.Configurations.Add(new vwCustomerConfiguration());
            Database.SetInitializer<TestDBContext>(null);
        

        public DbSet<Customer> Customer  get; set; 
        public DbSet<Addresses> Addresses  get; set; 
        public DbSet<Contacts> Contacts  get; set; 
        public virtual DbSet<vwCustomer> vwCustomers  get; set; 
        public DbSet<vwMyCustomers> vwMyCustomers  get; set; 
    

客户、地址、联系人和所有域类都在同一个项目中,但我想将所有这些域类放在不同的项目中。

只需查看我正在考虑实施的新项目层次结构。所有项目名称都以我的公司开头,然后是项目名称

在这里

1) Impex.Domain

2) Impex.Storage

3) Impex.Business

4) Impex.UI

所以我将有 4 层,分别是域、存储、业务和 UI。 Storage、Business 和 UI 这 3 层会有 Domain 层的引用,因为 Storage、Business 和 UI 这 3 层可能会用到领域类。

UI 将数据传递给业务层并从业务层接收数据。业务层再次与存储层对话,存储层将首先实现 EF 代码以与 DB 交互。

如果我能在 4 层之后成功完成我的项目,那么人们应该考虑我的项目是否基于 DDD 模式?

所以告诉我我的想法是否正确。请告诉我您的所有建议和指导。如果有人可以预见任何问题,那么也请详细了解我。谢谢

【问题讨论】:

看看这个amazon.co.uk/Modern-Web-Development-Understanding-technologies/…,它对你的帮助比你在这里得到的许多可能的答案要多。在这里你会得到很多回应,通常会与下一个发生冲突。购买此书,阅读此书,然后根据这让您思考的内容做出自己的判断和决定 我尝试将 DDD 与 EF 相结合的经验是,您可以使用您的域类型作为您的 EF 类型,但您必须在此过程中做出一些妥协。如果你想保持你的域完全干净并且与持久性无关 - 特别是如果你的域已经或将变得复杂 - 拥有一组作为你的 EF 类型的持久性模型,并将它们隐藏在你的存储库后面(我假设存储是?),并将两者完全分开。这是更多的工作,所以你需要评估它是否值得。 【参考方案1】:

您的问题似乎主要围绕您的解决方案的结构,就像我们行业中的大多数事情一样,一旦您了解了事物的原理(在本例中为 DDD),该结构似乎会自行解决。

我会指出一些事情来帮助你前进

1) Impex.Domain

保持你的实体干净不要从这个项目中引用 EF 在您的实体和聚合中而不是在“业务”层中捕获您的业务逻辑,您的实体应该响应事件和操作,而不是拥有一个告诉它要做什么的“层”

作为一个糟糕的例子,做类似的事情

employee.takeLeave(days)

代替

employee.daysOff = days;

即修改实体的状态应该在实体内部捕获。

2) Impex.Storage

由于您使用的是 EF(并且不会用 EF 相关属性污染您的域模型),您将不得不使用 Fluent Api 来配置您的 EF 模型(请参阅msdn、ef tuts 和 SO 到得到一些想法)特别是,这里需要配置主键和索引。

类似

modelBuilder.Entity<Employee>().HasKey(t => t.EmployeeID);
除了这里没有任何东西使用标准存储库模式等。

3) Impex.Business & Impex.UI

如第 1 点所述,拥有business 层没有意义,而该层将是ApplicationService 层,在这里您将加载实体或聚合并调用待完成的工作。 此外,该层的职责是在 ViewModel 和/或请求和响应 POCO 之间进行映射(发送到您的 UI/Api 和从您的 UI/Api 发送),您不会在域边界之外公开您的域模型,请参阅 hexagonal architecture

最后一点:

DDD 并不规定架构!这是一组指导您的原则,但您可以将其实现为 1 层、3 层、CQRS 或您喜欢的任何其他架构模式,只要您遵守 DDD 的租户即可。

祝你好运。

【讨论】:

以上是关于如何将领域类与EF代码第一层分离并在项目中实现DDD的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot+Vue前后端分离项目中实现编辑用户功能

Vue项目中实现用户登录及token验证

Vue项目中实现用户登录及token验证

SpringBoot+Vue项目中实现登录验证码校验

如何在 .NET EF Core 中实现自引用多对多关系

EF Core 中实现 动态数据过滤器