例如,假设我想为我的应用程序使用Entity Framework.但是,我也想在硬编码列表中实现一组测试数据.我想要有一组接口(IUserRepository,IProductRepository等 – 现在我们不再谈论一个更通用的IRepository&T),这两种方法都可以实例化.然后,使用(例如)依赖注入工具,如Ninject或Castle Windsor,我可以在实体框架提供者(访问实际数据库)和测试提供者(访问列表)之间来回切换.
简而言之,这里的问题是:
– 如果要使用Entity Framework,您希望您的存储库返回IQueryable< SomeType>.
– 如果要使用硬编码列表,您不希望您的存储库返回IQueryable,因为它增加了巨大的开销,而且,Linq to Entity与Linq对象大不相同,从而导致代码中的许多头痛这两个提供者都是共同的.
换句话说,我发现最好的方法是将存储库中的所有与EF相关的代码隔离开来,以便存储库本身返回IEnumerable或者IList或者一些这样的文件,那么EF和其他一些技术可以使用相同的存储库.因此,所有的IQueryable将被包含在EF存储库中.这样,您可以使用Linq到实体与EF存储库,以及Linq到具有测试存储库的对象.
然而,这种方法将大量的业务逻辑放入存储库,并导致重复的代码 – 即使实现有些不同,逻辑也必须在每个存储库中重复.
存储库作为这个非常薄且刚刚连接到数据库的层的整个想法然后丢失 – 存储库是业务逻辑的“仓库”以及数据存储连接.您不能只有查找,保存,更新等.
我无法解决这种差异,需要隔离与供应商相关的代码,并将业务逻辑集中在一个位置.
有任何想法吗?如果有人可以指出一个解决这个问题的实施的例子,我将非常感激. (我读了很多,但找不到任何具体谈论这些问题的东西.)
更新:
我想我开始觉得可能没有可以为不同的提供商交换存储库 – 例如,如果要使用Entity Framework,那么您只需将整个应用程序用于实体框架.单元测试?我正在努力.我到现在的做法是建立一个单独的硬件编码数据库,并将其用于单元测试,以及在数据库建立之前对应用程序本身进行测试.我想我将不得不寻找一个不同的解决方案,也许是一些嘲弄的工具.
但是那就提出了为什么使用存储库,特别是为什么使用存储库接口的问题.我在努力工作我认为确定最佳做法是要进行一些研究.
解决方法
您发现的是许多开发人员遇到的问题,这些开发人员使用EFv4进行“仓库繁荣”.是的,这是问题,问题真的很复杂.我几次讨论过:
> ASP.NET MVC 3 and Entity Framework code first architecture
> Organizationally,where should I put common queries when using Entity framework
单独的主题是为什么要使用存储库:
> Generic repository,what is the point
基本上你提出的方式是一个解决方案,但你真的想要吗?在我看来,结果不是存储库,而是数据访问对象(DAO)暴露了大量访问方法. Martin Fowler的存储库定义是:
A Repository mediates between the
domain and data mapping layers,acting
like an in-memory domain object
collection. Client objects construct
query specifications declaratively and
submit them to Repository for
satisfaction. Objects can be added to
and removed from the Repository,as
they can from a simple collection of
objects,and the mapping code
encapsulated by the Repository will
carry out the appropriate operations
behind the scenes. Conceptually,a
Repository encapsulates the set of
objects persisted in a data store and
the operations performed over them,
providing a more object-oriented view
of the persistence layer. Repository
also supports the objective of
achieving a clean separation and
one-way dependency between the domain
and data mapping layers.
我相信暴露的IQueryable可以达到100倍,然后创建一个类似于存储过程时代的存储库的公共接口 – 每个存储过程(固定查询)的一个访问方法.
该问题可以通过leaky abstraction的规则进行总结.IQueryable是数据库查询的抽象,但IQueryable提供的功能取决于提供程序.不同的提供者=不同的功能集.
有什么结论?你想要这样的架构,因为测试?在这种情况下,开始使用前两个链接答案中提出的集成测试,因为在我看来,这是最痛苦的方式.如果您使用您提出的方法,您仍然应该使用集成测试来验证您的存储库隐藏所有与EF相关的逻辑和查询.