让我们从两个引用开始,总结这个问题: “结束DbContext是一个漏洞的抽象。无论如何,你最终会在服务/控制器层中对EF产生某种依赖。” quote ref 第二个引用:
“DbContext Class
表示工作单元和存储库模式的组合,使您可以查询数据库并将更改组合在一起,然后将这些更改作为一个单元写回到商店。“MSDN
请不要说存储库模式允许您简单地换出数据库,但事实并非如此。有没有人用过成熟的应用程序做过这件事?另请注意,Repository模式不应该暴露IQueryable,我认为这只是另一种说法,你不相信与你合作的人。
我完全用于封装,代码覆盖/可测试性,但由于这种流行的回购模式为EF暴露了IQueryable,因此不再需要这种模式:
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);
}
存储库模式与UOW模式相结合的唯一好处是: 1.轻松启用依赖注入模式以提高可测试性/代码覆盖率 2.封装外部集成存在的复杂性(对不同供应商,Web apis,数据库等的Web服务调用。)
那么我通过使用MyDbContext:DbContext类得到的封装是什么?我的ORM是抽象当然我通过工作的UOW和常见的查询(如添加和删除)得到控制器的一些统一性,但这真的值得付出努力。我不能只相信我的开发人员是统一的,当他们按照自己的方式做到这一点时,就不要让OCD得到它。并且由于控制器可以编写它想要的任何查询,这不会在单元测试面前飞行吗? AND(甚至更大的大写lol)如果我有第三方API来调用,我可以在MyDbContext类中为控制器访问它,这看起来就像是对控制器的另一个数据调用。
我再说一遍,为什么不直接使用ORM,它就是数据抽象!
以下是针对存储库模式的一些参数:
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/
这是存储库模式的正确参数(尽管不够令人信服): http://www.sapiensworks.com/blog/post/2012/10/10/Do-We-Need-The-Repository-Pattern.aspx
答案 0 :(得分:6)
如果我再看到艾恩德的帖子,我想我会疯狂的。让我们慢慢来看看:
Generic Repository的适用性有限。就个人而言,我只将它用于域名存储库,并且只有当我以序列化形式存储聚合根时。对于其他内容(阅读:视图模型,报告),我有一个存储库,专为满足这些模型的层需求而设计。
IQueryable几乎是一个查询构建器。您没有告诉存储库如何来构建某些东西(IQUeryable),您只需要从中提出一些建议。如果您正在使用IQueryable,那么您已经在执行存储库工作的一部分(打破更高层的SRP)。同时暴露IQueryable意味着更高层必须知道用于创建查询的pocos /实体。如果您的老板决定从现在开始您将从Web服务获取数据,您会对所有那些洒在各处的IQueryable和ORM实体做些什么?或者RDBMS太慢所以让我们使用Document Db?是的,它可能会支持linq,但你确定你会定义相同的实体吗?
不要相信您的开发者。相信一个适当的架构,一个不混合层责任的架构,以及尊重SRP(单一责任原则)的架构。如果你正在进行设计,让我们说根据数据存储在数据库中的方式查看模型,而不是根据你在视图中的需要,你有一个紧耦合问题。
由于您不需要更改ORM或存储技术而不使用回购的原因是恕我直言的原因类似于:为什么使用DI容器或接口,这些类很少有机会改变,我们无论如何都可以做手动注射。
使用存储库意味着您无需关心如何以及从哪里检索模型。存储库公开了业务友好的语义(GetTopSellingProducts)。使用orm你必须构建查询(每个人都喜欢在linq中进行连接和子查询),了解实体,进行投影等。为什么更高层需要关注这些细节?这是'问,不说怎么'原则(j / k)
答案 1 :(得分:3)
我再说一遍,为什么不直接使用ORM,它就是数据抽象!
数据抽象而非 数据抽象。
如果您需要将其切换出来,那就是抽象您的ORM。不是关于通用回购可以直接提供给DbContext的好东西。如果您确实需要切换EF和DbContext并且它是高度耦合的,则需要编辑使用DbContext的代码的所有部分,或者强制在您切换到的任何ORM上实现DbContext接口。
我认为在大多数应用程序中切换ORM的可能性很小,并且直接使用DbContext的便利性超过了与EF耦合的风险。但是,我仍然明白为什么有些人会根据应用要求和使用寿命来做这件事。