Create new DbContext dynamically when using ASP.Net Core dependency injection

Mic*_*zyk 1 dependency-injection dbcontext asp.net-core

I've configured my DbContext with services.AddDbContext() in the Startup class and constructor injection in my controllers works very well.

默认情况下,它是一个范围服务,但我在应用程序中有一个地方,我想在单独的工作范围内更新实体的单个属性。所以我需要在控制器中创建一个新的 DbContext,但我不确定如何。我希望它由 DI 创建,因此我不必手动调用构造函数并提供所需的所有选项。有没有办法做到这一点?也许有办法从 DI 获取数据库上下文选项?然后我可以轻松构建 DbContext。

Mat*_*att 7

将 DbContext 注入控制器的正常方法可以正常工作,只要您在 HTTP 请求期间执行合理的工作量即可。但是,如果您正在运行后台/并行操作,或者如果您正在查询和修改大量记录(导致SaveChangesAsync()由于DbContext.ChangeTracker跟踪大量对象而陷入困境),您可能想要创建 DbContext 。如果是这样,您可以为每个操作创建一个作用域 DbContext。这是一个示例 ASP.NET Core 控制器方法:

    /// <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();
    }
Run Code Online (Sandbox Code Playgroud)

此外,我建议在 Startup.cs 中从 切换AddDbContext()AddDbContextPool()以避免为每个请求创建/销毁 DbContext 对象。DbContextPool 将在 DbContext 对象超出范围后将其重置为干净状态。(如果您感兴趣,DbContextPool 会调用DbContext.ResetState()DbContext.Resurrect(),但我不建议直接从您的代码中调用它们,因为它们可能会在未来版本中发生变化。) https://github.com/aspnet/EntityFrameworkCore/blob/v2。 2.1/src/EFCore/Internal/DbContextPool.cs#L157