12

我有一个asp.net.net MVC应用程序,最近开始实施与服务验证层的存储库模式,很像thisMVC存储库模式设计决策

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

对我来说,好像我要么用许多文件混淆项目树,要么用许多方法混淆一个类。 6方向打另一半。你能以任何方式想到任何好的论点吗?

回答

16

通常,如果您使用的是“真实”存储库模式,而不是其他持久层(例如ActiveRecord或DAO),则应该着眼于识别您的域聚合,并为每个聚合创建一个存储库。

这是什么意思?嗯,这取决于你的应用程序,但通常有些对象自然是其他对象的“父母”,或者是相关事务的一部分。

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

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

在这种情况下要记住的是,订单和订单行之间存在某种关系(暗示或其他方式)等等。因此,Repository上的“CRUD”的C-UD部分通常应该只是每个方法的一个方法,并且通常应该只接受该聚合根对象的一个​​实例并对其进行操作(例如.e.g。repo.Save(order))。其他可能的参数可能在那里,但这取决于你的impl。事实上,你通常可以解决绝大多数具有继承性的C-UD部分(即,使用一些已知逻辑来制作一个RepositoryBase,这个逻辑关于你的特定持久化方案会发生什么)。

这样就给我们留下了CRUD的R部分。在这种情况下,如果您选择执行查询方法路由,您可能会得到大量查询方法(GetById; GetByName; GetByCustomerName等)。有些人喜欢,尤其是简单的应用程序,暴露一个基于linq的接口(例如IQueryable GetAll()),然后可以应用Where子句。YMMV取决于你的潜在持久性,但它对于简单的应用程序来说是一个稳固的镜头,如果你期望持久化提供者直接支持linq。

最后,许多人通过命令查询责任分离模式的一个实现或另一个实际分离出查询部分,该模式表示用于持久化和查询的接口应该是不同的。在这种情况下,您将拥有一个只有基本CRUD(GetById,GetAll,Save,Delete)操作的回购,以及另一类根据您的应用意图查询事物的类。

希望有所帮助。

Paul

+0

Paul感谢您的详细解答。经过深思熟虑和阅读后,我觉得你发现每个聚合根目录有一个存储库/服务。您对CRUD也是正确的,每种方法都有C_UD和R的许多方法。在您的Order例子中,OrderRepository是否也会为OrderLines和OrderSubLines放置R方法? – bradjive 2010-03-17 13:26:28

+0

这是一个很好的问题,这取决于。订单和子行实际上是否意味着任何有用的W/O相关订单?如果是这样,那么是的,如果没有,那么你所有的查询都必须做w/Orders,你可以使用常规的LINQ表达式在IEnumerables上过滤子集合。 – Paul 2010-03-17 15:41:13

3

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

我最终得到了四个存储库,还有我的EF4实体模型的部分类扩展,用于子实体(地址,电话号码,状态代码等)的标准CRUD操作,因此它们实现了一次并可用于所有库。但是,我仍在继续细化,所以或许我还没有遇到最好的解决方案。

我的建议是尝试一下,看看它是否合适,看看它是否正确。通常,如果它不对感觉正确,反正它错了。

如果你真的害怕混乱你的源代码树,你总是可以将模型部分分解到它自己的库中,并将它作为依赖包含进来。