2011-03-29 82 views
3

我努力在.net解决方案中使用DDD实现一项要求。我会尽量减少细节:如何实现DDD存储库来处理具有多个实体的查询?

实体:

  • 类别(UID,名称)
  • 属性(UID,名称,AttributeValues [])
  • 的AttributeValue(UID,名称,ParentAttributeUId )
  • 过程(UID,名称,AttributeValues [],分类[])

数据模型:

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

我有S.P. FetchByCategoryAndAttributeValues(类别ID,AttributeValueIds []) 返回一个数据集:

  • 匹配类别ID过程的列表中,而且可用AttributeValueIds细化搜索AttributeValues的
  • 列表。

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

什么想法?

问候,

佩德罗

====编辑:2011/03/30下午2时52 UTC ====

我更新我的问题,珍惜所有的意见加上帮助其他人面临类似的挑战。

@Justice:

解决方案:使用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返回的计算会影响不同的模型。由于数据在数据库中的存在方式,常见的计算和计算在实体之间是有界的,所以问题在于如何实现DDD实现时如何获得最佳效果。以及如何保持数据库管理员的工作:)

您可以创建一个非常好的域模型,坚持数据跨越N个不同的表,问题是当您查询该数据如何使模型,并保持DDD处于良好的立场。

谢谢大家,我还在寻找创意,答案等:)

问候, 佩德罗

+0

刚刚看到您的更新。是的,保持DBA的工作是我们在最后一个地方努力奋斗的事情:P – Domenic 2011-04-17 05:42:39

回答

4

你眼前的问题是如何将在包含一些数据,以及一些“不相关”的数据,允许对数据进行与域模型一致的方式进一步过滤的数据集。

之所以这是一个问题,因为这个概念 - 带过来源性或外周相关数据的多个表不与域建模确实是一致的。领域建模是关于定义包含核心应用程序基本领域知识的关系和复杂业务逻辑。不产生基本相关对象的多个表格意味着它可能不是开始的领域模型的一部分。

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

解决方案还包括像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应用程序仍应建立在坚实的数据库和关系原则基础之上,并且性能没有任何问题。但是很多数据库服务器处理实际上都将域活动泄漏到数据库中。此外,很多这些最佳数据处理技术都违反了OOP和DDD的多重原则。

如果你不愿意完全放弃所有的数据库内容,并且它对你来说工作的很好,那么你可能不需要甚至不想移动到DDD概念。如果你想要DDD,最​​好的方法是考虑你拥有的所有东西作为宝贵的领域知识的来源,但是在实施细节方面,遗留代码正在被完全抛弃。 DDD并不适合将一个无DDD应用程序“移植”到。

1

使用NHibernate的。

让ORM 你的资料库。这就是它的目的。

+0

感谢您的评论,但对我而言,事情的美妙之处在于符合简单性。我有很多很好的T-SQL sps来完成这项艰苦的工作。我很想在ORM之外寻找解决方案。 – 2011-03-29 21:02:58

+0

像NHibernate一样的ORM *易于使用*和*强大*。您很可能不需要存储过程,任何复杂的域逻辑都可以轻松地作为实例/静态模型方法来处理。当你没有强大的工具时,存储过程是一个拐杖。 – yfeldblum 2011-03-30 00:11:41

+0

相关:http://ayende.com/Blog/archive/2009/08/15/the-least-common-denominator-approach.aspx – Domenic 2011-03-30 12:18:58

3

你需要以某种方式抽象的持久性代码。属于在基础结构层,而不是在域层(参见DDD第68页)。你可以手动完成这些工作,编写代码用DataSet或者使用像NHibernate这样的ORM。

如果您要手动执行此操作,我建议的模式与C#中Martin的Agile模式,实践和原则中的工资案例研究中探讨的模式类似。第569页的图表显示了他如何打包组件。

+0

感谢您的意见,我没有问题的坚持,那是由Process Repository处理。问题是如何处理直接提取不相关实体的SP。关于这本书,我会看看我想你提到第35章:访客。与DDD书相关的是关于基础设施层的权利? – 2011-03-29 21:36:07

+0

用于从数据库中提取事物的SP是持久性代码,不应直接从您的域层调用。由于存储库位于您的域图层中,因此您似乎有一个相当致命的缺陷...... – Domenic 2011-03-30 01:09:43

0

如果你已经在使用实体框架,有几个方法可以做到这一点(这个答案已经与佩德罗的重叠),每个都有自己的局限性&使用情况:

  1. 查询EF实体和回报DTO的。
  2. 直接使用DBContext的Database.SqlQuery查询SQL。如果您的DTO属性名称与您的SQL列匹配,那么它会为您映射它们。