You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Web API Core启动时用EF Core更新数据库报对象已释放错误如何解决

问题根因

  • PopulateSomeTable方法使用了async void签名,异步逻辑没有被等待就直接返回,Configure方法执行完毕后,从依赖注入容器解析到的SomeDBContext属于Scoped生命周期,会随方法执行结束被自动销毁,后续异步逻辑里再访问上下文就会触发已释放错误。
  • ASP.NET Core启动阶段直接在Configure方法参数中注入Scoped类型服务本身不符合生命周期规范,Scoped服务默认的作用域绑定请求链路,启动阶段没有请求上下文,直接注入的实例生命周期不受控。

修复方案

方案1:调整为同步初始化(快速修复)

将异步读写逻辑改成同步,保证所有数据库操作在Configure方法执行完毕前完成,避免上下文提前释放。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, SomeDBContext dataContext, ILoggerFactory loggerFactory)
{ 
    // 原有其他逻辑
    // 自动执行数据库迁移
    dataContext.Database.Migrate();

    PopulateSomeTable(dataContext);
}

private void PopulateSomeTable(SomeDBContext context)
{
    var someTables = context.SomeTables;
    if (someTables != null && someTables.Count() == 0)
    {
         someTables.Add(new Entities.SomeTable
         {
             someProperty1= 20,
             someProperty2 = "Something",
             someProperty3 = DateTimeOffset.Now,
         });
         context.SaveChanges();
    }
}

方案2:手动创建作用域执行异步初始化(规范推荐)

如果需要保留异步逻辑,手动创建Scoped作用域获取上下文,等待异步逻辑执行完成后再销毁作用域,完全符合依赖注入生命周期规则。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{ 
    // 原有其他逻辑
    // 手动创建作用域处理数据库操作
    using (var scope = app.ApplicationServices.CreateScope())
    {
        var dataContext = scope.ServiceProvider.GetRequiredService<SomeDBContext>();
        // 执行迁移
        dataContext.Database.Migrate();
        // 等待异步初始化完成再释放作用域
        PopulateSomeTableAsync(dataContext).Wait();
    }
}

// 异步方法签名改为返回Task,禁止用async void
private async Task PopulateSomeTableAsync(SomeDBContext context)
{
    var someTables = context.SomeTables;
    if (someTables != null && (await someTables.CountAsync()) == 0)
    {
         someTables.Add(new Entities.SomeTable
         {
             someProperty1= 20,
             someProperty2 = "Something",
             someProperty3 = DateTimeOffset.Now,
         });
         await context.SaveChangesAsync();
    }
}

注意事项

  • 除了系统事件回调场景外,禁止使用async void定义异步方法,统一使用Task/Task<T>作为返回值,方便调用方控制异步执行流程。
  • 启动阶段需要访问Scoped生命周期服务时,不要直接在Configure参数中注入,必须通过根服务提供者手动创建作用域后解析获取。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 02:15:07