如何实现 DDD 存储库来处理具有多个实体的查询?

Ped*_*ira 4 .net domain-driven-design

我正在努力在 .net 解决方案中使用 DDD 来实现需求。我会尽量减少细节:

实体:

  • 类别(UId、名称)
  • 属性(UId、名称、AttributeValues[])
  • 属性值(UId、名称、ParentAttributeUId)
  • 流程(UId、名称、AttributeValues[]、Categories[])

数据模型:

  • 每个进程可以有多个类别(例如 ProcessCategoryMap 表)
  • 每个 Process 可以有多个 AttributeValues(例如 ProcessAttributeValue 表)
  • 类别、属性、属性值之间没有关系

我有一个 sp FetchByCategoryAndAttributeValues(CategoryId, AttributeValueIds []) 返回一个数据集:

  • 匹配 CategoryId 和 AttributeValueIds 的进程列表
  • 可用于细化搜索的 AttributeValues 列表。

如何实现Repository加上调用SP的方法,当返回多个实体时,在我看来返回的对象是一个值对象并且它似乎不适合现有的实体存储库?

有任何想法吗 ?

问候,

佩德罗

==== 编辑:2011/03/30 02:52 PM UTC ====

我正在更新我的问题,以重视所有评论并帮助其他面临类似挑战的人。

@正义:

解决方案:使用 ORM,例如 NHibernate 加上使用 ORM 的所有理由

我不记得在 Eric Evans ddd 书中提到过 ORM。选择特定的持久性技术到底有什么影响?整理好域后,您可以随意保留它。Offcourse我知道NH可以提供帮助并且是强大的工具,但它本身并不是解决方案。

@Dominic / @Justice:

解决方案:远离存储过程。

首先,当我看到好的 T-SQL 存储过程时,对我来说很难证明,我不是在谈论 CRUD 或简单的 T-SQL 查询。我提到的 SP 运行一些 TSQL CTE,结合来自不同表的度量数据来计算权重,使用临时表并返回客观结果:进程列表、类别列表、属性值列表。SP 针对特定的 SQL 数据库/服务器进行了优化和调整,可以是 MSFT、Oracle 等。我不相信将这些计算转移到应用程序端,然后依赖 ORM 会帮助执行时间加上所有返回和转发查询。对我来说,在服务器中完成所有操作并仅带入过滤后的数据有很大的不同。我可能是错的。

@All:我已经确定了真正的问题(就像 Domenic 用 ayende 链接指出的那样)我正在将基于以数据为中心的方法的解决方案移植到域模型方法。让我们把这个放在一边,SP 返回的计算会影响不同的模型。由于数据保存在 DB 中的方式,实体之间存在常见的计算和计算,问题是何时转向 DDD 实现是如何获得两种实现的最佳效果。以及如何保留 DBA 的工作:)

您可以创建一个非常好的领域模型,将跨越 N 个不同表的数据持久化,问题是当您查询该数据时,如何将其引入模型并保持 DDD 的良好状态。

谢谢大家,我仍在寻找想法,答案等:)

问候,佩德罗

Sis*_*hus 5

您当前的问题是如何引入包含一些数据和一些“不相关”数据的数据集,以便以与域模型一致的方式进一步过滤该数据。

这是一个问题的原因是因为这个概念 - 带来多个派生或外围相关数据的表与域建模并不真正一致。领域建模是关于定义包含核心应用程序基本领域知识的关系和复杂的业务逻辑。不产生根本相关对象的多个表意味着它可能不是开始时域模型的一部分。

如果您没有本质上适合您尝试做的事情的对象,则意味着您的模型不完整,或者在这种情况下,您可能试图将应用程序的用户界面方面泄漏到域模型中。大概是后者。

解决方案是还包括一个用户界面视图架构,如 MVP 或 MVC。域对象是关于跨事务执行业务规则 - 保存和更新。例如,使用 DTO 和 Presenters 来组装任何类型的“新”或“混合”对象,这些对象不代表核心领域知识,而是被构造为以用户想要的某种方式向用户呈现数据。

在这种情况下,您只需创建一个 DTO,将 Process 和 Attribute DTO 合并到一个新对象中,以便在 UI 中使用。

但还有一些其他的可能性:

1) 有时您必须问自己是否使用了正确的工具来完成这项工作。我正在开发一个具有非常复杂域模型的医疗应用程序。这是核心应用程序 - 在数据采集过程中执行复杂的规则。但是一旦获得了这些数据,企业就有兴趣用它做许多不同的事情。获取模型和分析模型根本不合适,所以与其试图让它们一起工作,我认为更好的选择是拥有 DDD 的获取模型,然后使用 ETL 并将数据移动到数据仓库中,然后为业务提供基于查询而非 OOP/DDD 的单独分析应用程序。

2)领域建模是关于定义反映真实领域的模型,而不是关系数据技术。目标是管理复杂性并创建一个可以随着业务变化而改进和发展的模型。你不会发现很多人在做大量的 DDD,甚至会假装优化是其中的一个方面。相反,您尽可能使用 DDD 构建模型。如果您以后不得不妥协,那么您只能尽可能多地妥协该模型,以便将不可接受的性能带入可接受的范围内。

您可以使用更高效的查询做很多事情。当然,如果有人根本不知道该应用程序,他们可能必须追踪一堆这些东西,并且很可能必须或多或少地了解整个应用程序,然后才能理解其中的任何一个。DDD 当人们对应用程序的其余部分基本上一无所知时,您可以让他们成功地处理某些事情,但是在性能或往返行程方面,您甚至没有任何接近最佳的东西。

尽管它看起来很有吸引力和合乎逻辑,但它似乎试图两全其美,但我做 ETL 和数据仓库之类的核心 SQL 东西,我做 DDD。我对如何在一个应用程序中成功地合并两个世界有一些疑问。您最终得到的应用程序可能不是两全其美,而是没有人可以使用并且性能也不佳。如果你有一堆高效的存储过程,那里面肯定有一堆业务逻辑。如果您还有具有业务逻辑的“对象”,那么您最终得到的是数据库中的业务逻辑,“对象模型”中的业务逻辑结果只是(又一个)具有类的应用程序,但不是OOP 或 DDD - 几乎是人们多年来一直在做的事情,称之为“n 层”。

不要误会我的意思 - DDD 应用程序仍然应该建立在可靠的数据库和关系原则上,并且性能没有任何问题。但是很多 db 服务器处理实际上是将域活动泄漏到数据库中。此外,许多优化数据处理的技术违反了 OOP 和 DDD 的多项原则。

如果您不愿意完全放弃所有数据库内容,并且它对您来说效果很好,那么您可能不需要甚至不想首先转向 DDD 概念。如果您想要 DDD,最​​好的方法是将您拥有的一切视为有价值的领域知识的来源,但在实现细节方面,遗留代码已被完全放弃。DDD 并不真正适合“移植”非 DDD 应用程序。