【问题标题】:Using a POCO class as a domain class, but with custom link getters and setters?使用 POCO 类作为域类,但使用自定义链接获取器和设置器?
【发布时间】:2014-06-05 01:03:29
【问题描述】:

我最近了解到,使用代码优先设计它是一个好主意(使用实体框架时),POCO 类也与原始域类逻辑混合。

所以我决定使用这个新想法。之前(例如)我有一个名为 DatabasePerson 的 POCO 类和一个名为 Person 的域类。我现在正在尝试将它们合并为一个,以便让 Entity Framework 更好地管理我的存储库,并更轻松地管理对域层的更改。

现在,在我的 DatabasePerson POCO 课程中,我有一个指向 DatabaseAccount POCO 课程的链接。同样,我的Person 域类有一个指向Account 域类的链接。

在 Entity Framework 中,为了允许延迟加载这些类型的链接,我将链接属性声明为虚拟的(如在 DatabasePerson 类中),如下所示:

public virtual DatabaseAccount Account { get; set; }

但是,如果我想更改帐户的设置或获取方式,以及尝试将其设置为null 时如何处理异常,该怎么办?如何确保这不会与 Entity Framework 添加到表中的任何内容发生冲突?

这是我的域类的链接:

public Account Account {
    get {
        //maybe do some other stuff here.
        return account;
    }
    set {
        if (value == null) throw new ArgumentNullException("value");

        account = value;

        //maybe do some other stuff here.
    }
}

我想以某种方式保持这种形式的可定制性,但也有延迟加载。这可能吗?

【问题讨论】:

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


    【解决方案1】:

    延迟加载与领域驱动设计的概念相冲突,尤其是Aggregates 的概念。从存储库中检索和更新聚合应该是一个单一的操作。聚合需要按照通用语言的规范完成。引入延迟加载会破坏此规则,因为聚合不完整(或者这可能表明您没有正确定义聚合)。

    除了上述之外,你还违反了 DDD 的核心原则之一;您正在设计您的域,并受到技术问题(实体框架、数据库、延迟加载等)的强烈影响。引入这些基础设施“泄漏”将限制您做出设计决策的方式。实体和值对象构成了您领域的绝对核心。它们是彼此交互的真实世界对象。持久性无知是设计良好领域模型的关键。

    我会给你一个聚合的简短例子,但如果你想更好地掌握这个概念,你需要做更多的阅读。

    假设您已决定 Order 实体是聚合的根,该聚合包括 Order 和 OrderLine(Order 可以有 1 个或多个 OrderLine 实体)。这一决定可能基于多种原因,其中一些原因是:

    • OrderLine 无需独立于其Order 进行检索或引用
    • Order 应负责更改其 OrderLine“集合”
    • Order 及其 OrderLines 应该在事务上保持一致

    当从存储库中获取Order 时,该聚合将在单个工作单元中形成。所有OrderLines 都将与他们的订单一起获取并返回。保存或更新时,聚合也被持久化在单个工作单元中。这可确保所有实体(及其关系)保持一致,并且不会违反任何“业务规则”。

    在您的情况下,Person 和它们的Accounts 很可能不属于单个聚合。我假设您需要访问一个人的帐户,而无需检索该人本身(可能使用身份)。我假设您希望从聚合外部引用特定帐户(只能从聚合外部引用聚合根)。我还假设Account 可以独立于Person 改变。也许您不希望它属于 Person 聚合的另一个原因是由于性能原因(是的,有时我们必须务实而不是纯粹主义!)。以上所有内容完全取决于您的要求。

    我个人相信将您的数据实体(通常是使用实体框架或其他一些持久性工具从您的数据库直接映射)和您的域实体/值对象分开。这使您可以在与数据库相关的结构、框架和约束完全隔离的情况下设计您的域。

    【讨论】:

    • 使用实体框架,检索和更新聚合只是一个操作。而且您不必一直保存,您可以在需要时保存。考虑到这一点,您对此事是否仍有相同的看法?需要注意的是,Person 和 Account 在我的数据库中并不是真实的对象。我只是把它们作为一个例子。
    • @MathiasLykkegaardLorenzen 这不是意见,这就是 DDD 的工作方式,域优先,数据库不存在。域不知道您正在使用 EF,并且无论 ORM 或您是否首先使用数据库,域都应该相同。
    • 我只是认为这就是 POCO 的意义所在。使其更容易与域类集成。在 DDD 的世界中,我如何在数据库中存储东西?
    • 另外,考虑到 DDD,将实体框架与域类一起使用的正确方法是什么?
    • @MathiasLykkegaardLorenzen:在 DDD 世界中,没有数据库这样的东西!好的,在有时间和利益相关者压力的现实世界中,这是一个强有力的声明:)。无论如何,在域建模时尽量不要考虑数据库和关系数据结构是很重要的。您可以有一些驻留在域中的 IRepository 接口的 EF 具体实现(在 ninfrastructure 层中)。这些存储库接口处理域实体(准确地说是聚合)。您的 EF 类应该在您的 EF 数据实体和域模型之间进行映射。
    猜你喜欢
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2014-05-28
    • 2020-01-04
    • 2012-05-25
    • 2012-09-06
    • 2018-10-17
    • 1970-01-01
    相关资源
    最近更新 更多