使用存储库模式,支持多个供应商 [英] Using the repository pattern to support multiple providers

查看:219
本文介绍了使用存储库模式,支持多个供应商的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好了,不知道这是完全正确的标题,但基本上我一直有很多使用MVC应用程序库以这样的方式,你可以代替一组库的问题,实施了不同的数据存储技术,另一回事。

例如,假设我想使用实体框架我的应用程序。不过,我也希望有一个集硬件codeD列表实现的测试​​数据。我想有一组接口(IUserRepository,IProductRepository等 - 让我们不要谈论一个更通用的IRepository< T>现在)这两种方法可以实例。然后,使用(比如说)依赖注入工具,如Ninject或温莎城堡,我可以来回切换实体框架提供商(访问实际的数据库)和测试提供商(访问列表)之间。

在简单地说,这里有一个问题:

- 如果你要使用实体框架,你希望你的仓库返回的IQueryable< SOMETYPE取代。

- 如果你要使用硬codeD列表,您不希望您的仓库返回IQueryable的,因为它增加了巨​​大的开销,再加上,LINQ到实体是Linq的显著不同于对象,造成在code是常见的两种提供商许多头痛的问题。

在换句话说,我发现,最好的办法隔离所有的EF-依赖code的仓库内,从而使自己仓库的IEnumerable返回IList的,或或一些这样的 - 那么这两个EF和其他一些技术能够使用相同的存储库。因此,所有的IQueryable的将被包含在所述的EF库。这样一来,你可以使用LINQ到实体与EF库,和LINQ to对象的测试库。

然而,这种方法使业务逻辑的大量的入仓库,并导致许多重复code - 接收逻辑在每个存储库中被复制,即使实现方式有所不同<。 / p>

存储库,因为这一层,这是非常薄的,只是连接到数据库,将丢失的整体思路 - 存储库是业务逻辑的仓库,以及数据存储连接。你不能只是还查找,保存,更新等。

我一直未能解决需要隔离提供商依赖性code和有业务逻辑在一个集中的位置之间的差异。

任何想法?如果任何人都可以指向我针对这一问题实现的一个例子,我将不胜AP preciative。 (我读了很多,但无法找到任何具体谈这些问题。)

更新:

我想我开始觉得这可能不是可能有一个可以换出不同的供应商资料库 - 如果你要使用实体框架,例如,你只需要把你的整个应用程序实体框架。单元测试?我与挣扎。我这一点的做法是设置了硬codeD数据单独存储库,并利用它来进行单元测试,以及测试应用程序本身是建立在数据库之前。我想我将不得不寻求不同的解决方案,或许有些嘲讽的工具。

但随后引发为什么使用库的问题,特别是为什么使用存储库接口。我正在此。我认为,确定最佳的做法是要采取一些研究。


解决方案

我能说什么?欢迎来到俱乐部...

你所发现的是,许多开发商谁遵循库潮与EFv4达到的问题。是的,它是这个问题,这个问题是非常复杂的。我讨论了好几次:

独立的主题就是为什么要使用库:

基本上你提出的方法是一个解决方案,但你真的想要吗?在我看来,结果不是资源库,但数据访问对象(DAO)暴露大量的访问方法。由 Martin Fowler的存储库的定义是:


  

一个存储库之间调解
  域和数据映射层,演技
  就像一个内存域对象
  采集。客户对象构建
  查询规范和声明
  提交他们信息库
  满意。对象可以被添加到
  从资源库中删除,因为
  他们可以从一个简单的集合
  对象和映射code
  由存储库将封装
  进行适当的操作
  幕后。从概念上讲,
  资源库封装了一套
  对象持久化在数据存储和
  操作对他们进行的,
  提供一个更加面向对象的视图
  的持久层。知识库
  还支持的目标
  实现了完全分离并
  域之间的单向依赖
  和数据映射层。


我相信揭露的IQueryable 满足此100次更好然后创建类似于从存储过程的时代库公共接口 - 在每个存储过程(固定查询)一个访问方法。

这个问题可以通过漏抽象规则来概括。 的IQueryable 是数据库查询的抽象但的IQueryable 提供的功能都依赖于供应商。不同的供应商不同=功能集。

什么是结论?你想,因为测试这样的架构?在这种情况下,在第一次两个相连的答案,建议,因为在我看来,它是免得痛苦的方式开始使用集成测试。如果你与你提出的方法去,你还是应该使用集成测试,以验证库隐藏所有EF相关的逻辑和查询。

Well, not sure if that's exactly the right title, but basically I have been having a lot of problems using repositories in MVC applications in such a way that you can substitute one set of repositories, implementing a different data storage technology, for another.

For example, suppose I want to use Entity Framework for my application. However, I also want to have a set of test data implemented in hard-coded Lists. I would like to have a set of interfaces (IUserRepository, IProductRepository, etc. -- let's not talk about a more generic IRepository<T> for now) that both approaches can instantiate. Then, using (say) a Dependency Injection tool such as Ninject or Castle Windsor, I can switch back and forth between the entity framework provider (accessing the actual database) and the test provider (accessing the lists).

In a nutshell, here's the problem:

-- If you are going to use Entity Framework, you want your repositories returning IQueryable<SomeType>.

-- If you are going to use hard-coded lists, you do NOT want your repositories returning IQueryable, because it adds hugely to the overhead, and plus, Linq to Entities is significantly different from Linq to Objects, causing many headaches in the code that is common to both providers.

In other words, I have found that the best approach isolates all the EF-dependent code within the repositories, so that the repositories themselves return IEnumerable or IList or some such -- then both EF and some other technology can use the same repositories. Thus, all the IQueryable's would be contained WITHIN the EF repositories. That way, you can use Linq to Entities with the EF repositories, and Linq to Objects with the Test repositories.

Yet this approach puts an enormous amount of the business logic into the repositories, and results in much duplicated code -- the logic has to be duplicated in each of the repositories, even if the implementations are somewhat different.

The whole idea of the repositories as this layer that is very thin and just connects to the database is then lost -- the repositories are "repositories" of business logic as well as of data store connectivity. You can't just have Find, Save, Update, etc.

I've been unable to resolve this discrepancy between needing to isolate provider-dependent code, and having business logic in a centralized location.

Any ideas? If anyone could point me to an example of an implementation that addresses this concern, I would be most appreciative. (I've read a lot, but can't find anything that specifically talks about these issues.)

UPDATE:

I guess I'm starting to feel that it's probably not possible to have repositories that can be swapped out for different providers -- that if you are going to use Entity Framework, for example, you just have to devote your whole application to Entity Framework. Unit tests? I'm struggling with that. My practice to this point has been to set up a separate repository with hard-coded data and use that for unit testing, as well as to test the application itself before the database is set up. I think I will have to look to a different solution, perhaps some mocking tool.

But then that raises the question of why use repositories, and especially why use repository interfaces. I'm working on this. I think determining the best practice is going to take a bit of research.

解决方案

What I can say? Welcome to the club ...

What you found is problem reached by many developers who followed "repository boom" with EFv4. Yes it is the problem and the problem is really complex. I discussed this several times:

Separate topic is why to use repositories:

Basically your proposed way is a solution but do you really want it? In my opinion the result is not repository but the Data Access Object (DAO) exposing plenty of access methods. Repository definition by Martin Fowler is:

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.

I believe exposing IQueryable fulfils this 100 times better then creating a public interface similar to repositories from Stored procedures era - one access method per stored procedure (fixed query).

The problem can be summarized by the rule of leaky abstraction. IQueryable is an abstraction of the database query but the features provided by IQueryable are dependent on the provider. Different provider = different feature set.

What is a conclusion? Do you want such architecture because of testing? In such case start using integration tests as proposed in first two linked answers because in my opinion it is the lest painful way. If you go with your proposed approach you should still use integration tests to verify your repositories hiding all EF related logic and queries.

这篇关于使用存储库模式,支持多个供应商的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆