【问题标题】:Getting "'Cannot access a disposed object" error when trying to update database on startup using EF Core in Web API Core尝试在 Web API Core 中使用 EF Core 在启动时更新数据库时出现“'无法访问已处置的对象”错误
【发布时间】:2021-12-13 16:57:23
【问题描述】:

我们有一个 Web API Core 应用程序,它在后端使用 EF Core 和 SQL Server。我正在尝试在 Web API 服务启动时更新其中一个数据库表(在 Startup.cs 配置方法中)

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, SomeDBContext dataContext, ILoggerFactory loggerFactory)
{ 
    .......................
    // Automatically perform database migration
    dataContext.Database.Migrate();

    PopulateSomeTable(dataContext);
}

private async void PopulateSomeTable(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();
    }
}

但是,当我尝试访问上下文时出现此错误

无法访问已处置的对象。此错误的常见原因是 处理从依赖注入解决的上下文和 然后稍后尝试在您的其他地方使用相同的上下文实例 应用。如果您在 上下文,或将上下文包装在 using 语句中。如果你是 使用依赖注入,你应该让依赖注入 容器负责处理上下文

我该如何解决?

提前谢谢你

【问题讨论】:

    标签: c# dependency-injection entity-framework-core asp.net-core-webapi


    【解决方案1】:

    您需要将private async void PopulateSomeTable(SomeDBContext context) 替换为private async Task PopulateSomeTable(SomeDBContext context)。将async void 替换为async task。查看此link 了解更多信息。

    【讨论】:

      【解决方案2】:

      从启动中删除所有代码,这不是进行数据库迁移的最佳位置,并且只添加此代码

       public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, MyDbContext context)
          {
              if (env.IsDevelopment())
              {
                  context.Database.EnsureCreated();
               }
          }
      

      将此代码添加到启动的ConfigureServices中

      public void ConfigureServices(IServiceCollection services)
              {
                  services.AddControllers()
          .AddNewtonsoftJson(options =>
                 options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver());
      
      services.AddDbContext<SomeDBContext (options => 
      options.UseSqlServer(Configuration.GetConnectionString("CategoryDbConnection")));
      

      要填充数据,请添加类似 OnModelCreating of SomeDBContext 的代码

      modelBuilder.Entity<SomeTable>().HasData(
          new SomeTable{ ....
                       });
      

      要将类迁移到数据库表,请点击此链接 https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=vs

      【讨论】:

      • 谢谢!有没有快速引用数据库上下文的方法?
      • 如何调用 PopulateSomeTable?如何创建/引用 db 上下文变量?
      • @James 我更新了我的答案
      • 谢谢@Serge,代码可以编译,但数据库中没有保存,表保持为空:-(我需要应用一些额外的技巧/设置吗?
      • 请发布更新,我想看看你的hasdata,真正的。那里可能是一个错误
      猜你喜欢
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 2021-02-16
      • 2021-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-01
      相关资源
      最近更新 更多