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

发布于 2024-10-27 04:46:53 字数 1589 浏览 6 评论 0原文

我正在努力在 .net 解决方案中使用 DDD 来实现需求。我将尝试最小化细节:

实体:

  • 类别(UId,名称)
  • 属性(UId,名称,AttributeValues [])
  • AttributeValue(UId,名称,ParentAttributeUId)
  • 流程(UId,名称,AttributeValues [],类别[])

数据模型:

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

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

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

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

有什么想法吗?

问候,

Pedro

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

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

@Justice:

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

我不记得 Eric Evans ddd 书中提到过 ORM。选择特定的持久性技术有何重要意义?一旦您整理好域名,您就可以按照您希望的方式自由保留它。当然,我知道 NH 可以提供帮助并且是一个强大的工具,但它本身并不是一个解决方案。

@Dominic / @Justice:

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

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

@全部: 我已经确定了真正的问题(就像 Domenic 通过 ayende 链接指出的那样),我正在将基于数据中心方法的解决方案移植到域模型方法。让我们把这个放在一边,SP 返回的计算会影响不同的模型。由于数据在数据库中的持久化方式,存在常见的计算,并且计算在实体之间受到限制,因此问题是在转向 DDD 实现时如何充分利用这两种实现。以及如何保留 DBA 的工作:)

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

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

问候, 佩德罗

I'm struggling to implement a requirement using DDD in a .net solution. I'll try to minimize the details:

Entities:

  • Category (UId, Name)
  • Attribute (UId, Name, AttributeValues[])
  • AttributeValue (UId, Name, ParentAttributeUId)
  • Process (UId, Name, AttributeValues[], Categories[])

Data Model:

  • Each Process can have multiple Categories (e.g. ProcessCategoryMap table)
  • Each Process can have multiple AttributeValues (e.g. ProcessAttributeValue table)
  • No relation between category, attributes, attributeValues

I have a s.p. FetchByCategoryAndAttributeValues(CategoryId, AttributeValueIds [])
Returns a DataSet:

  • List of Processes matching CategoryId and the AttributeValueIds
  • List of AttributeValues available to refine the search.

How to Implement the Repository plus the method to call the SP, when multiple entities are returned, it seems to me that the object returned is a value object and it seems not fiting in the existent entities repositories ?

Any Ideas ?

Regards,

Pedro

==== Edit: 2011/03/30 02:52 PM UTC ====

I'm updating my question, to value all the comments plus to help others facing similar challenges.

@Justice:

solution: Use an ORM e.g. NHibernate plus all the justifications of using ORM

I don't recall any mention of an ORM in Eric Evans ddd book. How does the choice of a specific persistence technique matter at all ? Once you have the domain sorted out, you're free to persist it any way you wish. Offcourse i'm aware that NH can help and is powerful tool but it's not a solution per se.

@Dominic / @Justice:

Solution: Move away from Store Procedures.

First of all, for me is difficult to justify when i see good T-SQL stored procedure, I'm not talking about CRUD or simple T-SQL Queries. The SP that i mention runs a few TSQL CTE, combine metric data from different tables to calculate the weights, using temporary tables and returns objective results : List Of Processes, List of Categories, List of AttributeValues. The SP is optimized and tuned for a specific SQL database/server could be an MSFT, Oracle, etc. I don't believe that transferring those calculations to the Application side, and then relying in the ORM would help the execution time plus all back and forward queries. For me there is a big difference of doing all that in server and bringing only the filtered data. I could be wrong.

@All:
I've identified the real problem (like Domenic point out with the ayende link) I'm porting a solution based in a Data Centric approach to a Domain Model approach. Let's put this away, the calculations returned by the SP, affects different Models. Due the way data are persisted in the DB, there are common calculations and calculations are bounded between the entities, the question is when moving to a DDD implementation is how to get best of both implementations. And also how to keep the DBAs jobs :)

You can create a very good Domain Model, persist the data spanning over N different tables, The question is when you are querying that data how to bring to the Model and keep the DDD in good stand.

Thank you all, I'm still looking for ideas, answers, etc :)

Regards,
Pedro

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甜味超标? 2024-11-03 04:46:53

您面临的直接问题是如何引入包含一些数据和一些“不相关”数据的数据集,这些数据允许以与域模型一致的方式进一步过滤该数据。

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

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

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

在这种情况下,您只需创建一个 DTO,将流程和属性 DTO 合并到一个新对象中以供 UI 中使用。

但还有其他一些可能性:

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

2)领域建模是关于定义反映真实领域的模型,而不是关系数据技术。目标是管理复杂性并创建一个可以随着业务变化而完善和发展的模型。您不会发现很多人做了很多 DDD,甚至假装优化是其中的一个方面。相反,您构建的模型应尽可能与 DDD 一致。如果以后必须这样做,您只需尽可能地妥协该模型,以便将不可接受的性能纳入可接受的范围。

您可以使用查询做很多很多事情,而且效率要高得多。当然,如果有人根本不了解该应用程序,他们可能必须追踪一堆内容,并且很可能必须或多或少地了解整个应用程序,然后才能理解所有内容。 DDD 可以让人们在对应用程序的其余部分基本一无所知的情况下成功地完成某些工作,但在性能或往返方面却没有任何接近最佳的东西。

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

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

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

Your immediate problem is how to bring over a dataset that contains some data and and some "unrelated" data that allows that data to be filtered further in a fashion consistent with a domain model.

The reason why that is a problem is because the very concept - bring over multiple tables of derived or peripherally related data is not really consistent with domain modeling. Domain modeling is about defining the relationships and complex business logic that incorporate fundamental domain knowledge of the core application. Multiple tables that do not yield fundamentally related objects means it is probably not something that is part of the domain model to begin with.

If you don't have objects which are inherently suited for what you are trying to do it means either your model is incomplete, or in this case possibly that you are attempting to leak user interface aspects of the application into the domain model. Probably the latter.

The solution is to also include a user interface view architecture like MVP or MVC. Domain objects are about enforcing the business rules across transactions - saves and updates. Use DTOs and Presenters for example to assemble any sort of "new" or "hybrid" objects that do not represent core domain knowledge but are instead constructed to present the data to the user in some manner that the user wants.

In this case you just create a DTO that incorporates the Process and Attribute DTOs into a new object for consumption in the UI.

But there are some other possibilities:

1) There are times when you have to ask yourself if you are even using the right tool for the job. I am working on a medical application that has a very complex domain model. That is the core application - enforcing complex rules across the process of data acquisition. But once that data is acquired the business is interested in doing many different things with it. The acquisition model and the analytical model are not at all good fits, so instead of trying to make them work together I think the far better option to have the acquisition model which is DDD and then use ETL and move the data into a data warehouse and give the business a separate analytical application which is built on queries, not OOP/DDD.

2) Domain modeling is about defining models that reflect the true domain, not about relational data techniques. The objective is to manage complexity and create a model which can be both refined and evolved as the business changes. You will not find many people out there doing a lot of DDD that will even pretend that optimization is an aspect of that. To the contrary, you build a model as consistently with DDD as you possibly can. If you have to later you compromise that model only as much as you have to in order to bring unacceptable performance into an acceptable range.

There are lots and lots of things you can do with queries that are much more efficient. Of course if someone does not know the application at all they may have to trace a bunch of that stuff out and quite possibly have to more or less understand the entire application before they can understand any of it all. DDD you can have people working on something successfully when they know basically nothing about the rest of the application, but you don't have anything even close to optimal in terms of performance or round trips.

As attractive and logical as it seems to try for the best of both worlds, I do hardcore SQL stuff like ETL and data warehousing, and I do DDD. I have some doubts as to how successfully you can merge the two worlds in one application. Instead of the best of both worlds the chances are you will end up with an app no one can work with and does not perform well either. If you have a bunch of efficient stored procedures, there is bound to be a bunch of business logic in there. If you also have "objects" that have business logic then what you end up with is business logic in the database, business logic in the "object model" which turns out to be just (yet another) application that has classes, but is not OOP or DDD - pretty much the same thing people have already been doing for years and calling it "n-tier".

Don't get me wrong - DDD apps should still be built on solid database and relational principles and there is nothing wrong with performance. But a lot of db server processing is in effect domain activity leaked to the databases. Also a lot of these techniques of optimal data handling violate multiple principles of OOP and DDD.

If you are not willing to completely abandon all the database stuff, and it is working well for you, you may not need or even want to move to a DDD concept in the first place. If you want to DDD the best approach is to consider everything you have as a source of valuable domain knowledge but in terms of implementation details legacy code which is being completely abandoned. DDD is not really suitable for "porting" a none DDD app over to.

寄离 2024-11-03 04:46:53

您需要以某种方式抽象您的持久性代码。它属于基础设施层,而不是域层(参见DDD第68页)。您可以手动执行此操作,编写与 DataSet 混用的代码,或使用像 NHibernate 这样的 ORM。

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

You need to somehow abstract your persistence code. That belongs in an infrastructure layer, not in the domain layer (see DDD page 68). You can do this manually, writing code that mucks with DataSets, or using an ORM like NHibernate.

If you were to do it manually, the pattern I would recommend would be similar to that explored in the Payroll Case Study in Martin's Agile Patterns, Practices, and Principles in C#. The diagram around page 569 shows how he packages the components.

‘画卷フ 2024-11-03 04:46:53

使用NHibernate。

让 ORM 成为您的存储库。这就是它的用途。

Use NHibernate.

Let the ORM be your repository. That's what it's for.

秋心╮凉 2024-11-03 04:46:53

如果您已经在使用实体框架,有几种方法可以做到这一点(这个答案与 Pedro 的答案有重叠),每种方法都有自己的局限性和局限性。用例:

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

If you're already using Entity Framework, there are a couple of ways to do this (this answer has overlap with Pedro's), each with own limitations & use cases:

  1. Query EF entities and return DTOs.
  2. Query SQL directly using DBContext's Database.SqlQuery. If your DTO property names match your SQL columns then it maps them for you.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文