领域驱动设计:每个聚合根的存储库?
我正在尝试弄清楚如何完成以下任务:
User can have many Websites
在向用户添加新网站之前,我需要做的是获取网站 URL 并将其传递给一个方法,该方法将检查该网站是否已存在于数据库中(另一个用户具有关联的相同网站),或者是否创建新记录。 <= 原因在于是创建新缩略图还是使用现有缩略图。
问题是存储库应该是每个聚合根的,这意味着我无法执行上面解释的操作? - 我可以首先获取数据库中的所有用户,然后使用 if 语句进行 foreach 查找,检查用户在何处拥有具有相同 URL 的网站记录,但这会导致无休止且缓慢的过程。
I'm trying to figure out how to accomplish the following:
User can have many Websites
What I need to do before adding a new website to a user, is to take the website URL and pass it to a method which will check whether the Website already exist in the database (another User has the same website associated), or whether to create a new record. <= The reason for this is whether to create a new thumbnail or use an existing.
The problem is that the repository should be per aggregate root, which means I Cant do what I've Explained above? - I could first get ALL users in the database and then foreach look with if statement that checks where the user has a website record with same URL, but that would result in an endless and slow process.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
无论您使用哪种存储库方法,您都应该能够以某种方式指定标准。因此,搜索与相关网站关联的用户 - 如果搜索未返回任何用户,则该网站未被使用。
例如,您可以添加具有以下签名的方法(或者将查询对象传递为 本文中描述):
该方法应该生成或多或少像这样的 SQL:
这应该与查询
网站
直接上表;无需将所有用户和网站记录加载到内存中。让您的关系数据库承担繁重的工作,并让您的存储库实现(或对象关系映射器)处理翻译。Whatever repository approach you're using, you should be able to specify criteria in some fashion. Therefore, search for a user associated with the website in question - if the search returns no users, the website is not in use.
For example, you might add a method with the following signature (or you'd pass a query object as described in this article):
That method should generate SQL more or less like this:
This should be nearly as efficient as querying the
Website
table directly; there's no need to load all the users and website records into memory. Let your relational database do the heavy lifting and let your repository implementation (or object-relational mapper) handle the translation.我认为你的模型存在一个根本问题。如果我理解正确的话,网站是用户聚合组的一部分。这意味着网站实例不具有全局范围,它仅在属于用户的上下文中才有意义。
但现在,当用户想要添加新网站时,在创建新网站之前,您首先要检查“数据库中是否存在该网站”。这意味着网站实际上具有全球范围。否则,每当用户请求新网站时,您都将为该特定用户创建一个新网站,并且该网站在该用户范围内有意义。这里的网站是共享的,因此对许多用户来说有意义,因此不属于用户聚合的一部分。
修复你的模型,你就会解决你的查询困难。
I think there is a fundamental problem with your model. Websites are part of a User aggregate group if I understand correctly. Which means a website instance does not have global scope, it is meaningful only in the context of belonging to a user.
But now when a user wants to add a new website, you first want to check to see if the "website exists in the database" before you create a new one. Which means websites in fact do have a global scope. Otherwise anytime a user requested a new website, you would create a new website for that specific user with that website being meaningful in the scope of that user. Here you have websites which are shared and therefore meaningful in the scope of many users and therefore not part of the user aggregate.
Fix your model and you will fix your query difficulties.
一种策略是实现可以验证约束的服务。
然后你必须实现它,你如何做到这一点将取决于我不知道的因素,但我建议不要担心通过域。让它变得简单,这只是一个查询(* - 我将在底部添加到此)。
然后,将其“注入”到需要它的方法中。我说“注入”是因为我们将从域外部将其提供给域对象,但是..我们将使用方法参数而不是构造函数参数来执行此操作(以避免要求我们的实体由 IoC 容器实例化) )。
无论您的用户及其存储库的使用者是什么 - 如果是服务类或 CommandHandler - 都可以提供唯一性验证器依赖项。该消费者应该已经通过 IoC 连接起来,因为它将使用 UserRepository:
*我提到过使验证变得简单并避免域。
我们构建域来封装与修改数据相关的通常复杂的行为。
经验表明,更改数据的要求与查询数据的要求非常不同。
这似乎是您遇到的一个痛点,因为您试图强制读取通过写入系统。
可以将数据的读取与域、写入端分开,以减轻这些痛点。
CQRS 是该技术的名称。我只想说,当我在 CQRS 的上下文中查看 DDD 时,一大堆灯泡都亮了。我强烈建议尝试理解 CQRS 的概念。
One strategy is to implement a service that can verify the constraint.
You will then have to implement it, how you do that will depend on factors I don't know, but I suggest not worrying about going through the domain. Make it simple, it's just a query (* - I'll add to this at the bottom).
Then, "inject" it into the method where it is needed. I say "inject" because we will provide it to the domain object from outside the domain, but .. we will do so with a method parameter rather than a constructor parameter (in order to avoid requiring our entities to be instantiated by our IoC container).
Whatever the consumer of your User and its Repository is - if that's a Service class or a CommandHandler - can provide that uniqueness validator dependency. This consumer should already by wired up through IoC, since it will be consuming the UserRepository:
*I mentioned making the validation simple and avoiding the Domain.
We build Domains to encapsulate the often complex behavior that is involved with modifying data.
What experience shows, is that the requirements around changing data are very different from those around querying data.
This seems like a pain point you are experiencing because you are trying to force a read to go through a write system.
It is possible to separate the reading of data from the Domain, from the write side, in order to alleviate these pain points.
CQRS is the name given to this technique. I'll just say that a whole bunch of lightbulbs went click once I viewed DDD in the context of CQRS. I highly recommend trying to understand the concepts of CQRS.