DDD,实体框架和实体映射

时间:2016-10-03 12:35:17

标签: c# entity-framework domain-driven-design

我正在为下一个项目研究架构和模式。我正在考虑使用DDD,但由于该项目规模中等,我试图从代码重复和整体维护的角度尽可能简单。

图层如下所示,基本上每个图层都是一个单独的程序集:

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

对于数据库访问,我使用的是EF Core 1.0。

这是我目前设计(简化)的数据和域图层中的类,我对此并不满意。

域:

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

数据(EF):

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

理想情况下,我想直接使用我的域实体与ORM,但Task和TaskData不相同。在任务实体中我不需要导航属性CreatedBy,我只是一个Id,所以我不想用它不关心的东西污染域。

在数据模型中,我使用导航属性来处理某些报告,因此在某些情况下此连接很有用。

如您所见,如果我无法直接映射域实体,我必须在数据层中进行一些映射。更具体地说,在存储库中。手动映射器类。因为我的域实体没有公共getter和setter,所以我无法在属性的基础上将TaskData映射到Task实体。

这引出了memento模式,所以我创建了一个新类,它似乎只是简单的DTO:

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

我原来的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 };
  }
}

正如您所看到的,它需要三个具有不同目的的类,但是创建和维护的内容非常相似。它只是数据和域层。 “复制”也在其他层中继续。

现在当我决定添加一个新字段时,我需要记住添加它的所有地方并正确分配。我担心这会导致错误,因为团队中的某个人只是忘记更新所有代码。

我能做什么:

  1. 在域实体上公开getter和setter,因此我不需要Snapshot。 - > 绝对没有!

  2. 将不必要的属性(CreatedBy导航)添加到Task实体,并直接与ORM一起使用。 - > 我不愿意。

  3. 将Snapshot类转换为数据模型并将其与ORM一起使用。 - >我可能不介意那里的导航属性,但这意味着数据模型是域程序集的一部分。 - > 我不知道,我不喜欢它。

  4. 是否有建议如何有效减少课程数量或将 ALL 分配(映射)集中到一个地方/映射器类而不会损害域名?

    谢谢。

1 个答案:

答案 0 :(得分:0)

根据您在问题下面的评论,我要问的第一个问题是:为什么不想要域模型中的导航属性?如您所见,它使映射变得复杂,但具体有哪些优势?

另请查看here,其中说明:"通过关联属性导航是DDD中的关键概念。"

所以对我而言,听起来你可以通过在域模型中使用导航属性来保持简单 - 比如CreatedBy,为什么它不应该是你域中的核心概念?当然,如果明确请求,您可能希望禁用延迟加载并仅加载导航属性。