C# 正在寻找一种更有效的方法在startup.cs和controller中添加我的存储库

C# 正在寻找一种更有效的方法在startup.cs和controller中添加我的存储库,c#,asp.net,entity-framework,C#,Asp.net,Entity Framework,我正在使用实体框架存储库模式,我有很多存储库。现在,对于每个存储库,我将它们添加到startup.cs中,如下所示: services.AddScoped<IRepository, Repository>(); private readonly IRepository _repository; public Controller(IRepository repository){ _repository = repository; } 你可以想象,因为我有很多存储库,这些

我正在使用实体框架存储库模式,我有很多存储库。现在,对于每个存储库,我将它们添加到startup.cs中,如下所示:

services.AddScoped<IRepository, Repository>();
private readonly IRepository _repository;

public Controller(IRepository repository){
    _repository = repository;
}

你可以想象,因为我有很多存储库,这些列表会变得很长。看起来不太好。是否有一种更有效的方法来实现这一点?

如果您使用通用存储库模式或以其他方式定义每个实体的存储库,那么在使用EF时,您可能会遇到一个原因,我认为通用知识库模式是一种反模式。 如果您没有使用单元测试/w对依赖项进行模拟结构,那么存储库将变得非常冗余,而不仅仅是利用DBContext作为注入依赖项

例如,如果我有一个CreateOrderController,并且在创建订单的过程中,我需要有关客户、地址详细信息、产品、订单、供应商等的信息。使用通用存储库,我最终基本上会得到:

public CreateOrderController(IOrderRepository orderRepository, ICustomerRepository customerRepository, IProductRepository productRepository, ISupplierRepository supplierRepository, IAddressRepository addressRepository) // etc.
如果这是你所面临的噩梦,那么还有另一种选择。我发现比较容易管理的模式是定义范围为控制器或服务的存储库。该存储库负责该控制器/服务的所有数据层需求

如果我改为在一个存储库中管理与创建订单相关的所有实体,则该构造函数将变成:

public CreateOrderController(ICreateOrderRepository createOrderRepository)
CreateOrderRepository将具有检索订单、客户、产品、供应商等的方法,适用于创建订单流程的要求

这种方法的典型反论点是,它违反了“不要重复你自己”,因为几个控制器不可避免地想要检索客户或产品等。因此,像GetProducts这样的方法将出现在多个位置

这是一个简单的折衷方案,同时避免违反SRP单一责任原则,IMHO是比DRY更重要的原则。通用存储库的问题在于,它们看起来像是服务于一个单一的责任,即所有与产品相关的事情;它们要么以越来越低效或复杂的方式遵守SRP,要么违反SRP,因为任何给定的检索或以其他方式处理域的方法都服务于多个关注点,因此有许多原因需要更改

假设我们在CustomerRepository中有一个GetCustomer方法,该方法由3个以上不同的控制器调用,给它3个更改的理由。有些控制器需要相关数据,有些控制器只需要数据的一个子集,等等。当您面临一个控制器的需求略有不同的情况时,您将面临一个决策:

一切都以最低公分母标准化,坚持干法,这让一些消费者的效率比他们本来可以的要低。即获取所有字段或相关数据,即使他们不需要 引入复杂性以尝试满足每个人的不同需求,增加测试负载,因为复杂性为bug提供了隐藏的空间。也就是说,传递表达式或魔术字符串进行过滤、排序、快速加载,然后进行更多分页设置[当开发人员希望引入存储库来抽象出他们正在使用EF的事实时,我看到这是一个很好的选择…这不是使用存储库的一个很有说服力的理由。] 介绍几种不同的方法,它们做的事情彼此相似,以满足每个不同消费者的特定需求。违反DRY,并创建一个维护噩梦,记住哪种类似GetCustomer的方法适合特定的需求和重用噩梦 CreateOrderRepository中的GetCustomer方法只有一个原因需要更改。它只与createorder过程所需要的一样复杂,使其总体上更加简单,并且可以在不考虑其他依赖项的情况下进行调优

综上所述:两个思路要考虑…不要为存储库操心,使用DBContext,或者整合存储库,以便指定一个存储库来满足其控制器/服务的需要