使用EF Fluent API将域模型映射到数据库

时间:2013-12-13 11:55:30

标签: entity-framework domain-driven-design automapper domain-model onion-architecture

以下是通过Entity Framework 6 Fluent API直接映射到数据库的 Project 代码优先类:

public class Project
{
    public Project()
    {}

    public int ProjectId { get; set; }

    public string Name { get; set; }

    public bool IsActive { get; set; }

    public ICollection<ProjectVersion> ProjectVersions { get; set; }
}

域驱动设计中的贫血模型是一种反模式。我想在我的域模型中使用同一个类,而不是创建一个单独的Project域类,并且必须在存储库中的两个之间执行复杂的映射(以及其他数百个模型我们有)。

这就是Project看起来像域模型类的方式:

public class Project
{
    private readonly List<ProjectVersion> projectVersions;

    public Project(string name, string description)
    {
        Name = name;
        Description = description;
        projectVersions = new List<ProjectVersion>();
    }

    public int ProjectId { get; private set; }

    public string Name { get; set; }

    public bool IsActive { get; private set; }

    public IEnumerable<ProjectVersion> ProjectVersions 
    { 
        get
        {
            return projectVersions;
        }
    }

    public void AddVersion(ProjectVersion version)
    {
        projectVersions.Add(version);
    }
}

From what I have read,我可以使用EF的Fluent API映射到私有字段。

这里有什么缺点吗?我是否采取了不必要的捷径?

我可以预见的唯一问题是,业务领域模型基本上由来自两个或多个数据实体的数据组成。

2 个答案:

答案 0 :(得分:2)

我认为你在这种方法上犯了一个错误。我认为您应该将您的域模型的关注点与您的实体模型的关注点分开。鲍勃叔叔写了一篇关于此的奇怪但有点博客文章:Dance You Imps!(严肃地说,这是一个奇怪的帖子。)ORM的工作是作为你的数据库的合同。您的域模型的工作是提供功能。简而言之,您应该让Entity Framework以其想要的方式运行。如果要进行DDD,请编写映射层以将EF模型转换为域模型。

答案 1 :(得分:1)

  

这里有任何缺点吗?

可能。

EF确实可以解决私有成员问题,因此如果您愿意,可以使用加载的Project集合实现ProjectVersions。它不会使用AddVersion方法(它甚至不知道它存在),但它会将对象添加到projectVersions成员。

在应用程序代码中,您希望通过方法添加版本。但这种AddVersion方法可能存在一些问题。

  • 您始终可以添加ProjectVersion,但您永远不会确定是否会将其存储,因为要跟踪EF,必须加载projectVersions。但是,您不希望域实体负责从数据库加载自己的子项。所以AddVersion给了班级一个无法满足的责任。
  • 如果是对象,可以在生命期内的任何时刻调用AddVersion。通常这将比创建和跟踪它的上下文的生命周期长。因此,如果尚未加载集合,则不能依赖延迟加载来解决问题。 (顺便说一下,ProjectVersions应该virtual ICollection
  • 结论是,您必须始终projectVersions急切地(通过Include)加载AddVersion才能保证正常运行。因此,您的应用程序之间存在两个不明显相关的代码片段之间的依赖关系,这可能是错误的来源。
  • 当需要保存Project时,您必须将其附加到上下文,并找出哪个ProjectVersion应该标记为插入,哪个用于更新(甚至没有RemoveVersion 1}}方法。

总而言之,在服务方法中添加版本更简单,该方法在上下文的生命周期内执行所有必需的操作。添加的版本将被标记为自动插入。同样,任何更新和删除的版本都将被正确标记。