c# - 是 EF 实体或域对象的规范模式

标签 c# entity-framework domain-driven-design specification-pattern

我是领域驱动设计的新手,所以如果这个问题很微不足道,请原谅我。我正在阅读有关规范模式的内容,我相信理解了它的意图。网络上的大多数示例都在两个地方显示了其用法:

  1. 内部存储库方法

  2. 内部域服务/应用程序服务。

但这只有在 EF 实体和 Domain 对象相同的情况下才有效。我想这不被认为是一个好的实践(使用 EF 实体作为域对象)。 现在我的问题是 -

我们是否应该为域对象和 EF 实体编写不同的规范规则,或者是否有办法为两者重用相同的规则?我想如果我们不使用 C# 表达式并使用反射,我们可以以某种方式实现。

最佳答案

这是一个我非常关心的话题。 (直接答案如下)规范模式是不可知的。它所做的只是确定是否满足您定义(指定)的条件。它在这两个地方都很有用。我看到规范的两个主要好处:它命名您的业务规则,并隐藏(封装)您的实现。后续好处是,如果您愿意或提供易于理解的查询或规则列表,您可以锁定存储库。

应用于域对象的规范与用作查询的规范略有不同,但相当接近。 “QuerySpecification”中应包含目标存储库实现 (EF) 可以在数据库中获取和执行的查询语言,并返回 0 个或多个匹配项。

应用于域对象,它更常用于检查特定对象是否“符合规范”或过滤列表中的适用对象(排除或包含)。用法看起来不同,或者是同一概念的不同方面。

我谨不同意佐兰的建议。返回 IQueryable 意味着您赋予应用程序代码(可能是其他人的应用程序)直接查询数据存储的能力。延迟加载与急切加载也成为一个真正的纠结。我认为,你会失去封装性和实现隔离性。

还请记住,EF 代表 Repository 和 UnitOfWork 的实现。 DbContext 是工作单元,而 DbSet 是存储库。您应用自己的 DDD 接口(interface)的目标是确保您的域不依赖于 EF 实现,因此您的集成代码应该非常小。

所以,直接回答。

我建议向您的存储库接口(interface)添加一个方法,该方法接受 IQuerySpecification 并返回 T。您的实际规范是您的域的一部分。这些是您的组织所需的数据组合的规则。您可以将它们放入“共享内核”(库)中,或者根据您的需要将它们驻留在您的应用程序中。

请注意,理想情况下,通过使用查询规范,您可以消除经常弹出的所有特殊用途存储库函数,因为规范将要查询的内容与查询分开。埃里克·埃文斯写得更好:

The central idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched against. As well as its usefulness in selection, it is also valuable for validation and for building to order (https://www.martinfowler.com/apsupp/spec.pdf)

另请参阅https://matt.berther.io/2005/03/25/the-specification-pattern-a-primer/

关于c# - 是 EF 实体或域对象的规范模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40107834/

相关文章:

c# - 添加迁移时出现错误 'OracleInternal.Common.ODTSettings.m_bUseLongIdentifiers'

nhibernate - 处理 NHibernate 父子集合的最佳实践

asp.net - 在域驱动设计架构中使用数据填充域对象

domain-driven-design - 客户端是否应该检查后置条件/调用的方法是否应该检查前置条件?

c# - 值不能为空。参数名称 : source

c# - 使用 GUID 和 Entity Framework

c# - 无法在 Bluestacks 上连接/部署 Visual Studio Xamarin

c# - P/Invoke - Int 4 字节,尝试更改为 UInt 但它会导致问题

c# - Visual Studio 2010 中的构建问题

C# "Bad Data"解密加密文件时出现异常