简体   繁体   English

DDD,实体框架和实体映射

[英]DDD, Entity Framework and Entity Mapping

I'm currently working on an architecture and patterns for our next project. 我目前正在为下一个项目设计架构和模式。 I'm considering using DDD, but since the project will be of medium scale, I'm trying to make it as simple as possible from the perspective of code duplication and overall maintenance. 我正在考虑使用DDD,但是由于该项目将是中等规模的,因此我正在尝试从代码复制和整体维护的角度使它尽可能简单。

The layers look as follows, basically each layer is a separate assembly: 这些层如下所示,基本上每个层都是一个单独的程序集:

DB -> Domain -> Application -> Web API -> Clients

For DB access I'm using EF Core 1.0. 对于数据库访问,我使用的是EF Core 1.0。

Here is my current design (simplified) of the classes in data and domain layers and which I'm not very happy with. 这是我当前对数据和域层中的类的设计(简化),对此我不太满意。

Domain: 域:

class Task
{
  private int State { get; set; }
  private string Description { get; set; }
  private int CreatedById { get; set; }            
}

Data (EF): 数据(EF):

class TaskData
{
  public int State { get; set; }
  public string Description { get; set; }
  public int CreatedById { get; set; }
  public User CreatedBy { get; set; }
}

Ideally I would like to use my domain entity directly with the ORM, but the Task and TaskData are not identical. 理想情况下,我想直接将我的域实体与ORM一起使用,但是Task和TaskData是不同的。 In Task entity I don't need the navigation property CreatedBy, I'm fine with just an Id, so I don't want to pollute the domain with stuff it doesn't care about. 在Task实体中,我不需要导航属性CreatedBy,只需要一个ID就可以了,所以我不想用它不关心的东西来污染域。

In data model I'm using the navigation property for some reports, so this join is useful in some cases. 在数据模型中,我对某些报告使用了导航属性,因此此联接在某些情况下很有用。

As you can see, if I can't map domain entities directly, I have to do some mapping in the data layer. 如您所见,如果我不能直接映射域实体,则必须在数据层中进行一些映射。 To be more specific, in the repository via. 更具体地说,在存储库中通过。 manual mapper class. 手动映射器类。 Because my domain entity has no public getters and setters, I can't map TaskData to Task entity on a property basis. 因为我的域实体没有公共获取和设置器,所以我无法基于属性将TaskData映射到Task实体。

This leads me to memento pattern, so I create new class, which seems to be just plain DTO: 这导致我进入了记忆模式,因此我创建了新类,这似乎只是普通的DTO:

class TaskSnapshot
{
  public int State { get; set; }
  public string Description { get; set; }
  public int CreatedById { get; set; }
}

And my original Task entity looks now like: 我原来的Task实体现在看起来像:

class Task
{
  ...           
  public Task(TaskSnapshot snapshot)
  {
    this.State = snapshot.State;
    this.Description = snapshot.Description;
    this.CreateById = snapshot.CreatedById;
  }

  public TaskSnapshot ToSnapshot()
  {
    return new TaskSnapshot() 
    {
      State = this.State, 
      Description = this.Description, 
      CreatedBy = this.CreatedBy };
  }
}

As you can see, it takes three classes with different purpose, but very similar content to create and maintain. 如您所见,它需要三个目的不同的类,但是创建和维护的内容却非常相似。 And it's just data and domain layers. 它只是数据和域层。 The "duplication" continues in other layers too. “复制”也继续在其他层中进行。

Now when I decide to add a new field, I need to remember all the places where to add it and also correctly assign. 现在,当我决定添加一个新字段时,我需要记住所有要添加该字段并正确分配的位置。 I'm afraid this will often lead to bugs, because someone from the team just forgets to update all the code. 恐怕这经常会导致错误,因为团队中的某个人只是忘记更新所有代码。

What I could do: 我能做什么:

  1. Make getters and setters public on the domain entities, so I wouldn't need Snapshots. 在域实体上公开获取程序和设置程序,因此我不需要快照。 -> Definitely no! -> 绝对不行!

  2. Add unnecessary properties (CreatedBy navigation) to the Task entity and use it directly with ORM. 将不必要的属性(CreatedBy导航)添加到Task实体,并将其直接用于ORM。 -> I would rather not. -> 我宁愿不要。

  3. Transform Snapshot classes to data model and use them with ORM. 将Snapshot类转换为数据模型,并将其与ORM结合使用。 -> I probably wouldn't mind navigation properties there, but it would mean that data model is part of the domain assembly. ->我可能不介意那里的导航属性,但这意味着数据模型是域程序集的一部分。 -> I don't know, I don't like it. -> 我不知道,我不喜欢。

Is there a recommendation how could I effectively reduce number of classes or concentrate ALL the assignments (mapping) to one place/mapper class without compromising domain? 有没有建议我如何有效地减少类的数量或将所有分配(映射)集中到一个地方/映射器类而不影响域?

Thank you. 谢谢。

Based on your comment below your question, the first question I would ask is: why don't you want navigation properties in the domain model? 根据问题下方的评论,我要问的第一个问题是:为什么不想要域模型中的导航属性? As you see it complicates the mapping, but to what concrete advantage? 如您所见,它使映射变得复杂,但是有什么具体的优势呢?

Also take a look here , where is stated: "Navigation through association properties is a key concept in DDD." 还可以在此处查看 ,其中注明:“通过关联属性进行导航是DDD中的关键概念。”

So to me, sounds like you can keep things really simple by allowing navigation properties in your domain model - like CreatedBy, why should it not be a core concept in your domain? 因此,对我来说,听起来像可以通过允许域模型中的导航属性(例如CreatedBy)使事情变得非常简单,为什么它不应该成为域中的核心概念? Of course, you would want to disable lazy loading and only load navigation properties if requested explicitly. 当然,您可能希望禁用延迟加载,仅在明确请求时才加载导航属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM