0

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

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);
    }
}

根据我的阅读,我可以使用 EF 的 Fluent API 映射到私有字段。

这里有什么缺点吗?我是在走不必要的捷径吗?

我能预见的唯一问题是,当业务域模型本质上由来自两个或多个数据实体的数据组成时。

4

2 回答 2

2

我认为你在这种方法中犯了一个错误。我认为您应该将域模型的关注点与实体模型的关注点分开。鲍勃叔叔在这里写了一篇奇怪但很中肯的博客文章:跳舞你的小鬼!(说真的,这是一个奇怪的帖子。) ORM 的工作是充当数据库的合同。您的域模型的工作是提供功能。简而言之,您应该让 Entity Framework 以它想要的方式运行。如果您想做 DDD,请编写一个映射层将 EF 模型转换为您的域模型。

于 2013-12-13T22:23:06.207 回答
1

这里有什么缺点吗?

可能。

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

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

  • 您始终可以添加 a ProjectVersion,但您永远无法确定它是否会被存储,因为 EF 要跟踪添加的内容projectVersions必须已加载。但是,您不希望域实体负责从数据库中加载其自己的子实体。所以AddVersion给班级一个无法完全履行的责任。
  • AddVersion如果对象在生命周期内的任何时刻都可以调用。通常这将比创建和跟踪它的上下文的生命周期长。所以如果集合还没有加载,你不能依靠延迟加载来救援。(顺便说一句,ProjectVersions应该virtual ICollection为此)。
  • 结论是你总是必须projectVersions急切地加载(通过IncludeAddVersion才能保证正常工作。因此,在您的应用程序中,两个不明显相关的代码段之间存在依赖关系,这是潜在的错误来源。
  • Project需要ProjectVersion保存RemoveVersion.

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

于 2013-12-13T22:59:12.747 回答