Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具体的服务应该依赖于具体的存储库或接口吗?_C#_Entity Framework_Dependency Injection_Repository Pattern - Fatal编程技术网

C# 具体的服务应该依赖于具体的存储库或接口吗?

C# 具体的服务应该依赖于具体的存储库或接口吗?,c#,entity-framework,dependency-injection,repository-pattern,C#,Entity Framework,Dependency Injection,Repository Pattern,在使用ASP.NETMVC和EntityFramework时,我一直在努力实现存储库和服务模式 我了解存储库模式的用途,以及它如何帮助测试和使数据层可互换。然而,实体框架已经是一种存储库/工作单元模式。我所看到的存储库模式的每一个实现要么剥夺了它的有用特性,要么实现了一个IQueryable属性,这让纯粹主义者感到不安 如果我正在为我的服务层编写接口,那么实现这些服务的具体版本有没有理由不直接在服务中使用实体框架作为我的数据层(而不是将其包装在存储库/工作单元模式中并注入依赖关系)?例如:我不能

在使用ASP.NETMVC和EntityFramework时,我一直在努力实现存储库和服务模式

我了解存储库模式的用途,以及它如何帮助测试和使数据层可互换。然而,实体框架已经是一种存储库/工作单元模式。我所看到的存储库模式的每一个实现要么剥夺了它的有用特性,要么实现了一个
IQueryable
属性,这让纯粹主义者感到不安

如果我正在为我的服务层编写接口,那么实现这些服务的具体版本有没有理由不直接在服务中使用实体框架作为我的数据层(而不是将其包装在存储库/工作单元模式中并注入依赖关系)?例如:我不能创建一个
IService
接口,然后创建一个具体的
EfService
(实体框架)或
NhService
(NHibernate版本)实现吗

然后,我可以使用IoC容器注入所需的服务和数据上下文


下面是我根据Sergey的评论得出的一个例子:


这就是模式的实现方式吗?

我总是使用存储库接口

第一个原因是可测试性-
DbContext
DbSet
很难模仿。因此,即使可能,服务的单元测试也变得非常困难

第二个原因是
IQueryable
被EF公开。它使数据访问逻辑扩展到整个应用程序,这违反了SRP,使修复问题变得更加困难

第三个原因可能不是很重要——切换接口实现的能力——不仅适用于真实对象和模拟,而且适用于不同的数据访问框架。你总是想“不,我一定会坚持EF”。但在现实世界中,由于性能问题和开发的易用性,我有过切换到Dapper的经验。我曾经有过从内存数据存储切换到EF的经验。因此,拥有这个选项而不是依赖于特定于框架的API总是很好的

第四个原因是存储库提供的特定于域的API。你没有像
db.Orders.Where(o=>o.Category==“Food”)
那样的东西,而是有一个很好的方法
repository.GetOrdersByCategory

另一个原因是在一个地方有数据访问逻辑。没有重复。在上面的示例中,应用程序中可以有五个地方使用相同的查询按类别筛选订单。使用repository,您将有一个用于此目的的方法,该方法将在五个位置调用。考虑一下你的业务规则会发生什么变化吗?例如,您还需要检查类别是否处于活动状态


还请记住,一旦您拥有UoW和存储库基类和接口,就可以在不同的项目中重用它们。

Sergey,为什么需要模拟
DbContext
DbSet
?你就不能嘲笑这项服务吗?如果我看起来很天真,请原谅我。我试图理解这一点已经很长时间了,只是从来没有理解其目的。希望澄清。@Sam我说的是服务(或其他依赖于存储库的类)的单元测试,你有什么有用的例子可以指给我看吗?我正在努力了解存储库如何使您的服务更容易进行单元测试。@Sam您是否尝试过对依赖EF的服务进行单元测试?:)如果您在模拟存储库界面时遇到问题,那么可能是从存储库返回
IQueryable
。切换到
IEnumerable
,您将happy@Sam是的,没错。这是UoW和存储库的最简单实现,可以使用。通常,在存储库接口中还有方法
IEnumerable GetAll()
。如果您有大量的实体(即数据库中的表),那么您可以使用反射在UoW中实例化存储库。类似于泛型方法
GetRepository
。但我建议对start使用最简单的实现,正如您所指出的