首页 文章

使用ASP.Net Core依赖注入时动态创建新的DbContext

提问于
浏览
0

我已经在Startup类中使用了services.AddDbContext()配置了我的DbContext,并且我的控制器中的构造函数注入非常有效 .

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

2 回答

  • 1

    一种选择是将 IDbContextFactory 注入到您的comtroller中以在 using 块中创建上下文 .

    https://msdn.microsoft.com/en-us/library/hh506876(v=vs.113).aspx

  • 0

    只要您在HTTP请求期间执行了大量合理的工作,将DbContext注入Controller的常规方法就可以正常工作 . 但是,如果您正在运行后台/并行操作,或者您正在查询和修改大量记录(导致 SaveChangesAsync() 陷入困境,因为 DbContext.ChangeTracker 正在跟踪大量对象),您可能需要创建DbContext . 如果是这样,您可以为每个操作创建范围的DbContext . 以下是ASP.NET核心控制器方法的示例:

    /// <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();
        }
    

    另外,我建议在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

相关问题