我的应用程序分为几个程序集。
MyProject.Core 程序集包含所有域对象(例如 Person 和 Sale)以及接口存储库(例如 IPersonRepository 和 ISaleRepository)。
MyProject.Data 应该处理持久性,但我对它应该如何工作有点困惑。我应该使用实体框架将我的表映射到域模型吗?我应该使用 Fluent API 执行此操作吗?还是我应该实例化模型类并手动填充它们?
我的应用程序分为几个程序集。
MyProject.Core 程序集包含所有域对象(例如 Person 和 Sale)以及接口存储库(例如 IPersonRepository 和 ISaleRepository)。
MyProject.Data 应该处理持久性,但我对它应该如何工作有点困惑。我应该使用实体框架将我的表映射到域模型吗?我应该使用 Fluent API 执行此操作吗?还是我应该实例化模型类并手动填充它们?
IMO 您不应尝试将域模型对象用作实体框架实体。您将无法制作由原子方法组成的正确封装的域对象。相反,他们需要具有 EF 所需的带有 getter 和 setter 的公共属性,这会导致贫血域模型。
本质上:如果您尝试将域对象加倍为实体框架实体,您将损害设计。
相反,我使用了与memento 模式大致相似的东西,借此我使用充当“纪念品”的 EF 实体重新水合我的域对象。Vaugh Vernon 称这些对象为“状态对象”
鉴于 EF 可以只使用普通的 POCO,我会将这些类放在与托管 DbContext/Respositories 的程序集不同的程序集中,因为您的模型需要引用它们。因为它们只是 POCO,所以您不会将模型绑定到 EF。
所以你可能有三个程序集:
例子:
public class PersonRepository : EntityFrameworkRepository, IPersonRepository
{
public Person GetById(Guid personId)
{
using (MyDbContext ctx = new MyDbContext())
{
var personState = (from p in ctx.People
where p.PersonId == personId
select p).FirstOrDefault();
return Person.RestoreFromState(personState );
}
}
}
更新
借助 EF Core,您现在可以映射到私有字段,因此您可能不需要添加这种复杂程度来保持设计的完整性。
另外,我推荐 Vaughn Vernon 关于这个主题的以下帖子:https ://kalele.io/modeling-aggregates-with-ddd-and-entity-framework/
MyProject.Data 应该处理持久性,但我对它应该如何工作有点困惑。我应该使用实体框架将我的表映射到域模型吗?我应该使用 Fluent API 执行此操作吗?还是我应该实例化模型类并手动填充它们?
使用你所知道的,或者如果允许的话,你想学的。
无论哪种方式,您都不应该将任何数据库特定信息泄漏回域模型或对模型施加任何数据库限制。
行业标准做法是使用某种对象/关系映射器,例如实体框架或 NHibernate 等来加载和持久化您的实体。
O/RM 是在面向对象语言和关系数据库之间架起桥梁的工具。
它们通常与存储库模式结合使用。
使用这些工具不是必需的,您可以手动将实体保存到数据库,或者可能构建自己的 O/RM,但会给自己带来许多不必要的麻烦。通过使用 O/RM 工具,您将受益于许多其他构建 DDD 应用程序的经验。
值得指出的是,O/RM 不仅适用于 DDD 应用程序。
在我的应用程序中,数据层通常是一些存储库、NHibernate 映射文件和任何其他 NHibernate 实现代码。