MVC 存储库模式设计决策

发布于 2024-08-25 05:07:25 字数 330 浏览 3 评论 0原文

我有一个 asp .net MVC 应用程序,最近开始使用服务验证层实现存储库模式,很像 这个

我一直在为我创建的每个模型创建一个存储库/服务。这是否太过分了?相反,我是否应该为每个逻辑业务领域创建一个存储库/服务,为许多不同的模型提供 CRUD?

对我来说,似乎我要么用许多文件弄乱项目树,要么用许多方法弄乱一个类。 6 一种方式六种另一种方式。你能想出任何好的论据吗?

I have an asp .net MVC application and recently started implementing the repository pattern with a service validation layer, much like this.

I've been creating one repository/service for each model that I create. Is this overkill? Instead, should I create one repository/service for each logical business area that provides CRUD for many different models?

To me, it seems like I'm either cluttering the project tree with many files or cluttering a class with many methods. 6 one way half dozen the other. Can you think of any good arguments either way?

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

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

发布评论

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

评论(2

如果没有 2024-09-01 05:07:25

一般来说,如果您使用“真正的”存储库模式,而不是其他持久层(例如 ActiveRecord 或 DAO),您应该致力于识别您的域聚合,并为每个聚合创建一个存储库。

这意味着什么?嗯,这在很大程度上取决于您的应用程序,但通常有些对象自然是其他对象的“父对象”,或者是相关事务的一部分。

我认为典型的例子是一个电子商务系统,其中您有订单的概念,并且在订单中您有订单行,每个订单行都是一些产品和数量,等等。

在这种情况下,Order 对象是系统的聚合根之一,并且会创建 OrderRepository。

在这种情况下要记住的是,订单与其订单行等之间存在某种关系(隐含的或其他形式的)。因此,存储库上“CRUD”的 C-UD 部分通常应该只是每个方法,并且通常应该只接受该聚合根对象的一个​​实例并对其进行操作(例如 repo.Save(order))。可能还有其他可能的参数,但这取决于您的实现。

事实上,您通常可以通过继承来解决大部分 C-UD 部分(即创建一个 RepositoryBase,使用一些关于您的特定持久性方案应该发生什么的已知逻辑来实现它们)。

这样我们就剩下 CRUD 的 R 部分了。在这种情况下,如果您选择采用查询方法路线,您可能会获得大量查询方法(GetById、GetByName、GetByCustomerName 等)。有些人更喜欢(特别是对于简单的应用程序)公开基于 linq 的接口(例如 IQueryable GetAll()),然后可以应用Where 子句。 YMMV 取决于您对该应用程序的潜在持久性,但对于简单的应用程序来说,它是一个不错的选择,尤其是。如果您希望持久性提供程序直接支持 linq。

最后,许多人实际上通过命令查询职责分离模式的一种实现来分离查询部分,该模式表示用于持久化和查询的接口应该是不同的。在这种情况下,您将拥有一个仅具有基本 CRUD(GetById、GetAll、Save、Delete)操作和另一个根据应用​​程序意图查询内容的类的存储库。

希望有帮助。

保罗

Generally, if you're using a "true" Repository Pattern, as opposed to other persistence layers (e.g. ActiveRecord or DAO's), you should aim to identify your domain aggregates, and create one repository per aggregate.

What does that mean? Well, it depends a lot on your app, but generally there are objects which are naturally 'parents' of other objects, or which are part of a related transaction.

I think the canonical example is an ecommerce system in which you have a concept of an order, and in an order you have orderlines each orderline is some product and a quantity, and so on.

In that case, the Order object is one of the system's aggregate roots and an OrderRepository is created.

The thing to remember in that case is that there's some relationship (implied or otherwise) between a order and its orderlines and so on. So the C-UD parts of "CRUD" on the Repository should generally just be one method each, and should generally just take in an instance of that aggregate root object and operate on it (.e.g. repo.Save(order)). Other possible params might be there, but that depends on your impl.

IN fact, you can often solve most of the C-UD part w/ inheritance (i.e. make a RepositoryBase that implements them using some known logic about what shoudl happen for your particular persistence scheme).

So that leaves us the R part of CRUD. In this case is where you might get a ton of query methods (GetById; GetByName; GetByCustomerName, etc) if you choose to go the query method route. Some folks prefer, espeically for simple apps, exposing a linq-based interface (e.g. an IQueryable GetAll()) that can then have Where clauses applied. YMMV depending on your underlying persistence on that one, but it's a solid shot for simple apps, esp. if you expect your persistence provider to support linq directly.

Lastly, many folks actually separate out the query part via one implentation or another of the Command Query Responsibility Separation pattern, which says the interfaces for persisting and querying should be different. IN that case, you'd have a Repo that just has basic CRUD (GetById, GetAll, Save, Delete) ops and another class of some sort which queries things based on your app's intentions.

Hope that helps.

Paul

守不住的情 2024-09-01 05:07:25

这是我最近问的一个问题,尽管得到了几个很好的答案,但我最终得出了自己的结论——没有正确的答案。这并不意味着没有错误的答案,事实上有很多错误的答案,但正确的答案始终取决于您自己的个人情况。

我最终得到了四个存储库,以及 EF4 实体模型的部分类扩展,用于子实体的标准 CRUD 操作(地址、电话号码、状态代码等),因此它们只需实现一次即可在所有存储库中使用。然而,我仍在不断完善它,所以也许我还没有找到最好的解决方案。

我的建议是尝试一下,看看是否合适,看看感觉是否合适。通常,如果感觉不对,那么它无论如何都是错的。

如果您真的害怕弄乱源代码树,您可以随时将模型部分分解到它自己的库中,并将其作为依赖项包含在内。

This is a question I recently asked, and despite getting several good answers I eventually came to my own conclusion - there is no right answer. That doesn't mean there isn't a wrong answer, infact there are lots of wrong answers, but the right answer will always depend on your own individual case.

I ended up with four repositories, and a partial class extension of my EF4 Entity Model for the standard CRUD actions for the child entities (addresses, phone numbers, status codes et al) so they were implemented once and available across all repositories. However, I am still refining it as I go, so perhaps I haven't yet come across the best solution.

My advice would be to try it and see if it fits, and see if it feels right. Usually, if it doesnt feel right, its wrong anyway.

If you are really afraid of cluttering up your source code tree, you can always break the model part out into its own library, and include it as a dependency.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文