我最近了解到(使用Entity Framework时)设计代码优先是一个好主意,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.
}
}
我想以某种方式保持这种形式的可定制性,但也有延迟加载。这可能吗?
答案 0 :(得分:2)
延迟加载与域驱动设计的概念冲突,尤其是Aggregates的概念。从存储库检索和更新聚合应该是单个操作。根据无所不在的语言中的规范,聚合需要完整。引入延迟加载会破坏此规则,因为聚合不完整(或者这可能表示您未正确定义聚合)。
除此之外,您还违反了DDD的核心原则之一;您正在设计具有技术问题(实体框架,数据库,延迟加载等)的强大影响的域。引入这些基础设施“泄漏”将限制您做出设计决策的方式。实体和价值对象构成了您域名的绝对核心。它们是彼此交互的真实世界对象。持久性无知是设计良好领域模型的关键。
我将举一个关于聚合的简短例子,但如果你想更好地掌握这个概念,你需要做更多的阅读。
假设您已确定Order
实体是包含Order
和OrderLine
的聚合的根(Order
可以包含1个或多个OrderLine
OrderLine
1}}实体)。这个决定可以基于很多原因,其中一些是:
Order
无需独立检索或引用Order
Order
应负责更改其OrderLine'集合'OrderLines
及其Order
应具有交易一致性从存储库中获取OrderLines
时,此聚合将在单个工作单元中形成。所有Person
将使用其订单获取并返回。保存或更新时,聚合也会保留在单个工作单元中。这可确保所有实体(及其关系)保持一致,并且不会违反“业务规则”。
在您的情况下,Accounts
及其Account
很可能不属于单个聚合。我假设您需要访问一个人的帐户而无需检索该人本身(可能使用身份)。我假设您将要引用聚合外部的特定帐户(只能从聚合外部引用聚合根)。我还假设Person
可以独立于{{1}}进行更改。也许你不希望它属于Person聚合的另一个原因是由于性能原因(是的,有时我们必须务实而不是纯粹!)。以上所有完全取决于您的要求。
就个人而言,我相信将您的数据实体(通常是使用Entity Framework或其他一些持久性工具从您的数据库直接映射)与您的域实体/值对象分开。这使您可以完全隔离与数据库相关的结构,框架和约束来设计域。