尝试在 Web API Core 中使用 EF Core 在启动时更新数据库时出现“'无法访问已处置的对象”错误

Posted

技术标签:

【中文标题】尝试在 Web API Core 中使用 EF Core 在启动时更新数据库时出现“\'无法访问已处置的对象”错误【英文标题】: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 语句中。如果你是 使用依赖注入,你应该让依赖注入 容器负责处理上下文

我该如何解决?

提前谢谢你

【问题讨论】:

【参考方案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,真正的。那里可能是一个错误

以上是关于尝试在 Web API Core 中使用 EF Core 在启动时更新数据库时出现“'无法访问已处置的对象”错误的主要内容,如果未能解决你的问题,请参考以下文章

要在 EF Core 中添加没有外键的导航属性,使用 .NET Core Web API 进行 DB-first 迁移

EF Core 5.0 - 更新 ASP.NET Core Web API 中的多对多实体

带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何

这是从 ASP.NET Core Web API 中的 EF Core 5 获得的啥样的响应 [关闭]

使用EF Database-First Application部署ASP.NET Web API

EF Core 6.0 导航属性未加载