无法使用单例的作用域服务

Joj*_*ojo 1 c# asp.net-core-mvc .net-core asp.net-core

我正在尝试在托管服务中使用DBContext,但收到此错误。我尝试遵循此已 接受的答案,但是以某种方式无法正常工作,我不确定自己在做什么错。

我是.net的新手,请引导我朝正确的方向发展。

未处理的异常:System.InvalidOperationException:无法使用单例“ Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor”中的作用域服务“ StatusApp.Context.DBContext”。

public class TokenService : IHostedService
{
    public IConfiguration _Configuration { get; }
    protected IMemoryCache _cache;
    private Timer _timer;
    public IHttpClientFactory _clientFactory;
    public DBContext _DBcontext;

    private readonly IServiceScopeFactory _scopeFactory;

    public TokenService(IConfiguration configuration, IMemoryCache memoryCache, IHttpClientFactory clientFactory, DBContext DBcontext, IServiceScopeFactory scopeFactory)
    {
        _Configuration = configuration;
        _cache = memoryCache;
        _clientFactory = clientFactory;
        _scopeFactory = scopeFactory;
        _DBcontext = _scopeFactory.CreateScope().ServiceProvider.GetRequiredService<DBcontext>();
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _timer = new Timer(getOrg, null, 0, 1000);
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        //Timer does not have a stop. 
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }

    public async Task getOrg()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, "organizations");
        var response = await _client_NP.SendAsync(request);
        var json = await response.Content.ReadAsStringAsync();
        OrganizationsClass.OrgsRootObject model = JsonConvert.DeserializeObject<OrganizationsClass.OrgsRootObject>(json);

        foreach (var item in model.resources)
        {
            var g = Guid.Parse(item.guid);
            var x = _DBcontext.Organizations.FirstOrDefault(o => o.OrgGuid == g);
            if (x == null)
            {
                _DBcontext.Organizations.Add(new Organizations
                {
                    OrgGuid = g,
                    Name = item.name,
                    CreatedAt = item.created_at,
                    UpdatedAt = item.updated_at,
                    Timestamp = DateTime.Now,
                    Foundation = 3
                });
            }
            else if (x.UpdatedAt != item.updated_at)
            {
                x.CreatedAt = item.created_at;
                x.UpdatedAt = item.updated_at;
                x.Timestamp = DateTime.Now;
            }
        }

        await _DBcontext.SaveChangesAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

Kir*_*kin 6

您快到这里了,但是您已经DBContext成为TokenService的构造函数中的依赖项。删除它,您将不再收到错误。

公共TokenService(
    IConfiguration配置,
    IMemoryCache memoryCache,
    IHttpClientFactory clientFactory,
    DBContext DBcontext,
    IServiceScopeFactory scopeFactory)

但是,您不太遵循有关DbContext在单例服务中处理的建议。与其DBContext在构造函数中创建单个实例并将其存储为字段,不如DBContext在需要时创建范围和相应的范围。就您而言,这就是getOrg方法。

请按照以下步骤来实现:

  1. _DBcontext从您的TokenService班级中删除该字段:

    公共DBContext _DBcontext;

  2. TokenService构造函数中删除关联的分配:

    _DBcontext = _scopeFactory.CreateScope()。ServiceProvider.GetRequiredService <DBcontext>();

  3. 在中getOrg,创建作用域,解析该作用域的实例DBContext,最后处置该作用域:

    public async Task getOrg()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, "organizations");
        var response = await _client_NP.SendAsync(request);
        var json = await response.Content.ReadAsStringAsync();
        OrganizationsClass.OrgsRootObject model = JsonConvert.DeserializeObject<OrganizationsClass.OrgsRootObject>(json);
    
        using (var scope = _scopeFactory.CreateScope())
        {
            var dbContext = scope.ServiceProvider.GetRequiredService<DBcontext>();
    
            foreach (var item in model.resources)
            {
                var g = Guid.Parse(item.guid);
                var x = dbContext.Organizations.FirstOrDefault(o => o.OrgGuid == g);
                if (x == null)
                {
                    dbContext.Organizations.Add(new Organizations
                    {
                        OrgGuid = g,
                        Name = item.name,
                        CreatedAt = item.created_at,
                        UpdatedAt = item.updated_at,
                        Timestamp = DateTime.Now,
                        Foundation = 3
                    });
                }
                else if (x.UpdatedAt != item.updated_at)
                {
                    x.CreatedAt = item.created_at;
                    x.UpdatedAt = item.updated_at;
                    x.Timestamp = DateTime.Now;
                }
            }
    
            await dbContext.SaveChangesAsync();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

_DBContext上面的代码没有使用该字段,而是创建了一个适当范围的局部变量,dbContext并使用了该变量。

  • 这是因为回调的签名应该是“void”,但你的签名是“Task”。David Fowler 在[此处](https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/master/AsyncGuidance.md#timer-callbacks)提供了一些关于处理此问题的很棒的建议。 (2认同)