我已在Startup类中使用services.AddDbContext()配置了我的DbContext,并且我的控制器中的构造函数注入效果非常好。
默认情况下,它是一个范围内的服务,但我在应用程序中有一个位置,我希望在单独的工作范围内更新实体的单个属性。所以我需要在控制器中创建一个新的DbContext,但我不确定如何。我希望它由DI创建,所以我不必手动调用构造函数并提供所需的所有选项。有没有办法做到这一点?也许有一种方法可以从DI获取数据库上下文选项?然后我可以轻松地构建DbContext。
答案 0 :(得分:2)
将DbContext注入Controller的常规方法可以正常工作,只要您在HTTP请求期间进行了合理的工作即可。但是,如果您正在运行后台/并行操作,或者正在查询和修改很多记录(由于SaveChangesAsync()
正在跟踪{很多对象)。如果是这样,则可以为每个操作创建一个有作用域的DbContext。这是一个示例ASP.NET Core Controller方法:
DbContext.ChangeTracker
此外,我建议在Startup.cs中从 /// <summary>
/// An endpoint that processes a batch of records.
/// </summary>
/// <param name="provider">The service provider to create scoped DbContexts.
/// This is injected by DI per the FromServices attribute.</param>
/// <param name="records">The batch of records.</param>
public async Task<IActionResult> PostRecords(
[FromServices] IServiceProvider provider,
Record[] records)
{
// The service scope factory is used to create a scope per iteration
var serviceScopeFactory =
provider.GetRequiredService<IServiceScopeFactory>();
foreach (var record in records)
{
// At the end of the using block, scope.Dispose() will be called,
// releasing the DbContext so it can be disposed/reset.
using (var scope = serviceScopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetService<MainDbContext>();
// Query and modify database records as needed
await context.SaveChangesAsync();
}
}
return Ok();
}
切换到AddDbContext()
,以避免为每个请求创建/销毁DbContext对象。 DbContextPool超出范围后,会将DbContext对象重置为干净状态。 (如果您有兴趣,DbContextPool会调用AddDbContextPool()
和DbContext.ResetState()
,但是我不建议直接从您的代码中调用它们,因为它们可能会在将来的版本中更改。)
https://github.com/aspnet/EntityFrameworkCore/blob/v2.2.1/src/EFCore/Internal/DbContextPool.cs#L157
答案 1 :(得分:0)
一种选择是将IDbContextFactory
注入您的comtroller以在using
块内创建上下文。
https://msdn.microsoft.com/en-us/library/hh506876(v=vs.113).aspx