我正在尝试在托管服务中使用DBContext,但遇到此错误。 我尝试遵循this接受的答案,但是以某种方式无法正常工作,我不确定自己做错了什么。
我是.net的新手,请引导我正确的方向。
未处理的异常:System.InvalidOperationException:无法使用 单例的作用域服务“ StatusApp.Context.DBContext” “ Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor”。
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();
}
}
答案 0 :(得分:6)
您快到了,但是您已经将DBContext
保留为TokenService
的构造函数中的依赖项。删除它,您将不再收到错误。
public TokenService( IConfiguration configuration, IMemoryCache memoryCache, IHttpClientFactory clientFactory,DBContext DBcontext,IServiceScopeFactory scopeFactory)
但是,您不太遵循有关在单例服务中处理DbContext
的建议。与其在构造函数中创建DBContext
的单个实例并将其存储为字段,不如在需要时创建范围和相应的DBContext
。对于您来说,这是在getOrg
方法中。
请按照以下步骤操作:
从您的_DBcontext
类中删除TokenService
字段:
public DBContext _DBcontext;
从TokenService
构造函数中删除关联的分配:
_DBcontext = _scopeFactory.CreateScope().ServiceProvider.GetRequiredService<DBcontext>();
在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();
}
}
上面的代码没有使用_DBContext
字段,而是创建了一个适当范围的局部变量dbContext
并使用了它。