我正在尝试在托管服务中使用 DBContext,但出现此错误。
我试图遵循 this 接受的答案,但不知何故它不起作用,我不确定我做错了什么。
我是 .net 新手,请指导我走向正确的方向。
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();
}
}
IServiceScopeFactory scopeFactory)
However, you're not quite following the recommendation for dealing with DbContext
's in a singleton service. Instead of creating a single instance of DBContext
in the constructor and storing it as a field, create a scope and a corresponding DBContext
whenever you need it. In your case, that's in the getOrg
method.
Follow these steps to achieve that:
Remove the
_DBcontext
field from yourTokenService
class:Remove the associated assignment from the
TokenService
constructor:In
getOrg
, create a scope, resolve an instance ofDBContext
and, lastly, dispose of the scope: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
并使用它。关于c# - 无法从单例使用范围服务,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57580937/