通用存储库模式+ UOW模式与ORM(如实体框架)有什么优势? [英] What are the advantages to the Generic Repository Pattern + UOW Pattern with an ORM like Entity Framework

查看:174
本文介绍了通用存储库模式+ UOW模式与ORM(如实体框架)有什么优势?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们先从两个引号中总结出这个问题:
包装DbContext是一个漏洞的抽象,无论你在服务/控制器层中,你最终会遇到某种依赖于EF。 报价参考
和第二个报价:



DbContext Class



表示工作单位和存储库模式的组合,并使您查询数据库并将更改组合在一起,然后将其作为一个单位写回商店。 MSDN



请不要说存储库模式允许您简单地交换数据库,但是没有。有没有人甚至用成熟的应用程序做到这一点?也请不要回答,Repository模式不应该暴露IQueryable,我认为这只是另一种说法,你不信任你所使用的人。



我是所有这些都用于封装,代码覆盖/可测试性,但是由于EF的这种流行的回购模式暴露了IQueryable,所以不再需要这种模式:

  public interface IRepository< T>其中T:class 
{
IQueryable< T>得到所有();
T GetById(int id);
IEnumerable< T> Get(Expression< Func< T,bool>> filter = null,Func< IQueryable< T>,IOrderedQueryable< T> orderBy = null,string includeProperties =
void Add(T entity);
void Update(T entity);
void Delete(T entity);
void Delete(int id);
}

存储库模式与UOW模式结合的唯一好处是:
1.轻松启用依赖注入模式,提高可测试性/代码覆盖率
2.封装外部集成(Web服务调用到不同的供应商,Web apis,数据库等)的复杂性。 >

那么使用MyDbContext:DbContext类,我得到什么封装?我的ORM是抽象当然,我有一个统一的控制器与工作的UOW和常见的查询,如添加和删除,但这是真的值得的努力。我不能相信我的开发人员是统一的,当他们做一点他们的方式,只是不要得到OCD。并且由于控制器可以写任何查询,它希望这不会面对单元测试飞? AND(甚至更大的盖帽)如果我有一个第三方API来调用,我可以使这个可访问的MyDbContext类为控制器,所以它似乎只是另一个数据调用控制器。



我再说一遍,为什么不直接使用ORM,这是数据抽象!



这是一些反对存储库模式的参数:



http://ayende.com/blog/4784/architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer



http://ayende.com/blog/3955/repository-is-the-new-singleton





http://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/



这是存储库模式的一个正确的参数(不够令人信服):
http://www.sapiensworks.com/blog/post/2012/10/10/Do-We-Need-The-Repository-Pattern .aspx

解决方案

我想我会去笨蛋,如果我看到Ayende再发一次。让我们慢慢来看一下:


  1. 通用存储库的适用性有限。就个人而言,我仅在域存储库中使用它,只有当我将序列化表单中的聚合根存储时,才使用它。对于其余的事情(阅读:查看模型,报告),我将有一个专为满足这些模型的层需求而设计的存储库。


  2. IQueryable几乎是一个查询构建器。你不会告诉存储库如何构建一些东西(IQUeryable),你只需要问一些东西。如果您使用的是IQueryable,那么您已经在部署存储库的工作(打破了较高层的SRP)。还暴露IQueryable意味着更高层必须知道用于创建查询的pocos /实体。如果您的老板决定从现在开始,您将从网络服务中获取数据,那么所有这些IQueryable和ORM实体会在哪里处理?或者RDBMS太慢了,所以让我们用一个Document Db?是的,它可能会阻止linq,但是你确定定义了相同的实体吗?


  3. 不要相信你的开发者。相信一个合适的架构,一个你不会混合层次责任的地方,SRP(单一责任原则)在哪里得到尊重。如果您正在设计,我们来说,根据数据存储在数据库中的方式查看模型,而不是根据视图中需要的内容,您会遇到紧耦合问题。


  4. 因为不需要更改ORM或存储技术,不使用repo的原因是IMHO的原因类似于:为什么使用DI容器或接口,这些类会改变的机会很小,而且我们也可以手动注入。


  5. 使用存储库意味着您不必关心 您的模型被检索。存储库暴露了商业友好的语义(GetTopSellingProducts)。使用orm,您必须构建查询(每个人都喜欢在linq中进行连接和子查询),了解实体,做预测等。为什么上层关心这些细节?这是'问,不要说'原则(j / k)


所有的,我想让我的代码很容易理解。


Let's start with two quotes that sums this issue up: "Wrapping up DbContext is a leaky abstraction. No matter what, you'll end up in some kind of dependency on EF in your services/controller layer." quote ref And the second quote:

"DbContext Class

Represents a combination of the Unit-Of-Work and Repository patterns and enables you to query a database and group together changes that will then be written back to the store as a unit." MSDN

Please do not say that the repository pattern allows you to simply swap out your database, it does not. Has anyone even ever done that with a mature application? Please also do not answer that the Repository pattern should not expose IQueryable, I think that is just another way saying you don't trust the people you work with.

I am all for encapsulation, code coverage/testability but since this popular repo pattern for EF exposes IQueryable there is no longer a need for the pattern it seems:

   public interface IRepository<T> where T : class
    {
    IQueryable<T> GetAll();
    T GetById(int id);
    IEnumerable<T> Get(Expression<Func<T, bool>> filter = null,Func<IQueryable<T>,IOrderedQueryable<T>> orderBy = null, string includeProperties = "");
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
    void Delete(int id);
}

The only benefits of the repository pattern combined with the UOW pattern are: 1. Easily enable the Dependency Injection pattern for increase testability/code coverage 2. Encapsulate the complexity that exists with external integration (web service calls to different vendors, web apis, databases, etc..)

So what encapsulation am I getting that I do not get by using MyDbContext : DbContext class? My ORM is the abstraction Sure I get some uniformity of the controllers with the UOW of work and the common queries like Add and Delete, but is that really worth the effort. Can't I just trust my developers to be uniform and when they do it a little their way, just don't get OCD about it. AND since a controller can write any query it wants does this not fly in the face of unit testing? AND (even larger caps lol) if I have a third party API to call, I can make this accessible in MyDbContext class for the controllers so it seems like just another data call to the controller.

I say again, why not use the ORM directly, it is the data abstraction!

Here is some arguments against the repository pattern:

http://ayende.com/blog/4784/architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer

http://ayende.com/blog/3955/repository-is-the-new-singleton

http://lostechies.com/jimmybogard/2012/09/20/limiting-your-abstractions/

http://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/

Here is a proper argument for the repository pattern (not convincing enough though): http://www.sapiensworks.com/blog/post/2012/10/10/Do-We-Need-The-Repository-Pattern.aspx

解决方案

I think I'll go bonkers if I see that Ayende post one more time. Let's take each thing slowly:

  1. Generic Repository has limited applicability. Personally, I'm using it ONLY for domain repositories and ONLY when I'm storing the aggregate roots in a serialized form. For the rest of things (read: view models, reports) I'd have a repository designed for the needs of the layer asking for those models.

  2. IQueryable is pretty much a query builder. You don't tell the repository how to build something (IQUeryable) you just ask something from it. If you're using IQueryable you're already doing part of the repository's job (breaking the higher layer's SRP). Also exposing IQueryable means the higher layer MUST know about pocos/entities used to create the query. IF your boss decides that from now on you'll get the data from a web service, what would you do with all those IQueryable and ORM entities sprinkled everywhere? Or the RDBMS is too slow so let's use a Document Db? Yes, it might suport linq but are you sure you'll have the same entities defined?

  3. Don't trust your developers. Trust a proper architecture, one where you don't mix layer responsibilities and where SRP (Single Responsibility Principle) is respected. If you're designing, let's say View Models according to how data is stored in db and not according what you need in a view, you have a tight coupling problem.

  4. The reason of not using a repo because you don't need to change the ORM or the storage tech is IMHO a reason similar to: why use a DI Container or interfaces, there is a slim chance those classes would change and we can do manual injection anyway.

  5. Using a repository means you don't have to care about how and where from your models are retrieved. The repository exposes business friendly semantics (GetTopSellingProducts). With an orm you have to build the query (everybody loves doing joins and subqueries in linq), know about the entities, do the projections etc. Why should the higher layer care about these details? It's the 'ask, don't tell how' principle (j/k)

It's all about maintainable code after all, I want my code to be easily understood.

这篇关于通用存储库模式+ UOW模式与ORM(如实体框架)有什么优势?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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