c# - ASP.NET Core - 单例注入(inject)时存储库依赖项注入(inject)失败

标签 c# asp.net-core dependency-injection asp.net-core-mvc entity-framework-core

我正在使用SoapCore为我的 ASP.NET Core MVC 应用程序创建 Web 服务。

我正在使用 Entity Framework Core 和简单的存储库模式来获取我的数据库数据。

我通过 Startup.cs 中的 .AddSingleton() 注入(inject)我的存储库类:

services.AddSingleton<IImportRepository, ImportRepository>();
services.AddSingleton<IWebService, WebService>();

由于 EF DbContext 已确定范围,因此我在调用 Web 服务时收到错误:

Cannot consume scoped service 'App.Data.ApplicationDbContext' from singleton 'App._Repository.IImportRepository'.

当我使用 .AddScoped() 时,它工作正常。

我读过通过 Controller /类构造函数注入(inject)作用域依赖项是一种不好的做法,因为它“回落”为单例或表现得像单例。

我想知道是否有另一种方法可以让它与单例一起工作,或者当通过 ctor 在我的 Controller 中使用作用域注入(inject)时,从长远来看这是否有一些主要缺点(大约 100-200 个用户将使用该网站)?

最佳答案

简单地说,你的生命周期应该是“范围化的”。如果您有充分的理由,那么您应该只使用单例或 transient 生命周期。对于单例来说,这类似于管理锁或保存需要在应用程序的生命周期内持续存在的数据,这两者都不适用于存储库的概念。存储库应该是完全一次性的。关键是要持久化到数据库或其他存储,因此它们本身不应该包含任何需要持久化的数据。

总而言之,你最好的选择就是简单地让你的存储库范围化,这样你就可以直接注入(inject)上下文。就构造函数注入(inject)而言,我不确定您从哪里得知这是一种不好的做法。事实上,这就是大多数情况下依赖注入(inject)的工作原理,因此两者缺一不可。

如果您绝对需要有一个单例,那么您唯一的选择是服务定位器反模式。为此,您将注入(inject) 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
}

关于c# - ASP.NET Core - 单例注入(inject)时存储库依赖项注入(inject)失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57495333/

相关文章:

C# 如果在组合框 winform 中选择了某些文本

c# - 替换字符串中的多个范围

c# - 仅本地主机端点

asp.net-core - 如何注入(inject)对特定 IHostedService 实现的引用?

c# - ASP.NET MVC 对象引用未设置为对象的实例

c# - 设备上的 NotSupportedException

c# - Azure 应用服务简单端点的响应非常慢

c# - ASP.NET Core - 对 WebAPI 使用 Cookie 和 JWT

c# - Autofac 从 Container 解析构造函数实例?

具有动态参数的 Angular Factory Provider