[英]ASP.NET Core - Repository dependency injection fails on Singleton injection
我正在使用SoapCore为ASP.NET Core MVC应用程序创建Web服务。
我正在使用Entity Framework Core和简单的存储库模式来获取我的数据库数据。
我通过Startup.cs中的.AddSingleton()
注入存储库类:
services.AddSingleton<IImportRepository, ImportRepository>();
services.AddSingleton<IWebService, WebService>();
由于EF DbContext
具有作用域,因此在调用Web服务时出现错误:
无法使用单例“ App._Repository.IImportRepository”中的作用域服务“ App.Data.ApplicationDbContext”。
当我改用.AddScoped()
,它可以正常工作。
我读过通过controllers / classes构造函数注入作用域的依赖关系是不好的做法,因为它“回退”为单例或行为类似。
我想知道是否有另一种方法可以使它与单例一起使用,或者通过ctor在我的控制器中使用作用域注入时,从长远来看是否会有一些重大缺点(大约100-200个用户将使用该站点)?
简而言之,您的终生应该受到“限制”。 仅在有充分理由的情况下才应使用单例或瞬态寿命。 对于单例来说,诸如管理锁或保存数据等在应用程序的整个生命周期中都需要持续存在的东西,都不适用于存储库的概念。 储存库应该完全是一次性的。 关键是要保留到数据库或其他存储中,因此它们不应自行包含任何需要保留的数据。
总之,最好的选择是使存储库范围有限,以便您可以直接插入上下文。 就构造函数注入而言,我不确定这是一个不好的做法。 实际上,在大多数情况下这就是依赖注入的工作原理,因此您不能一无所有。
如果您绝对需要单身人士,那么唯一的选择就是服务定位器反模式。 为此,您将注入IServiceProvider
:
public class MyRepo
{
private readonly IServiceProvider _serviceProvider;
public MyRepo(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
...
}
然后, 每当需要上下文时 (这很重要),就需要执行以下操作:
using (var scope = _serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<MyContext>();
// do something with context
}
作用域对象不能注入到单例对象中。 如此简单,单例仅在应用程序启动时创建一次,并被所有后续请求使用。 范围对象在每个请求期间创建,并在请求结束时处理。 因此,先前创建的单个对象无法知道在每个请求期间创建的作用域对象。 因此,不可能在单例中使用范围对象。 但是反之亦然。
通过控制器/类构造器注入作用域依赖
我认为这不是一个坏习惯。 如果不是,您打算如何进行单元测试?
同样,使数据库上下文单例也是不正确的。 您将同时面临现金问题/数据异常以及后续要求。 在我看来,必须确定数据库上下文的范围,并且必须将使用db-context的所有对象一直确定范围。
因此,在所有情况下,使所有对象ImportRepository,WebService和DB Context都具有作用域。
干杯,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.