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

ASP.NET项目使用EF Core Migrate时触发System.ExecutionEngineException异常

解决ASP.NET WebApi + EF Core 2.0.2 + SQLite进程回收后迁移异常的问题

我之前维护WebApi项目时也碰到过几乎一模一样的问题,结合你的描述,核心问题大概率是SQLite文件锁机制+迁移执行时机不当导致的——尤其是Release模式下没有调试器兜底,异常直接中断了流程。下面给你几个针对性的解决方案:

1. 不要在应用启动同步流程中执行迁移

很多人习惯在Startup.Configure里同步调用dbContext.Database.Migrate(),但进程回收重启时,IIS可能还没完全释放之前的数据库连接句柄,导致SQLite文件被锁。建议把迁移改成后台异步执行,避开应用启动的关键流程:

public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
{
    // 其他中间件配置(路由、CORS等)...

    // 把迁移放到后台任务执行,不阻塞应用启动
    Task.Run(async () =>
    {
        using (var scope = serviceProvider.CreateScope())
        {
            var dbContext = scope.ServiceProvider.GetRequiredService<YourDbContext>();
            try
            {
                await dbContext.Database.MigrateAsync();
            }
            catch (Exception ex)
            {
                // 添加日志记录,方便排查异常原因
                // 比如:scope.ServiceProvider.GetRequiredService<ILogger<Startup>>().LogError(ex, "数据库迁移失败");
            }
        }
    });
}

2. 调整SQLite连接字符串参数,减少锁冲突

SQLite是文件级锁,进程回收后的残留连接很容易导致锁异常。修改你的连接字符串,添加几个关键参数:

"ConnectionStrings": {
  "YourDbConnection": "Data Source=your_database.db;Cache=Shared;Mode=ReadWriteCreate;Pooling=false"
}
  • Cache=Shared:允许多个进程共享数据库缓存,降低锁竞争概率
  • Pooling=false:关闭连接池,避免旧的连接池连接持有文件锁不释放
  • Mode=ReadWriteCreate:确保应用有读写权限,同时不存在数据库时自动创建

3. 给迁移添加重试机制,处理临时锁异常

Debug模式下你点击取消后能成功,本质是第一次迁移因为锁失败,第二次尝试时锁已经释放了。在Release模式下,我们可以用重试策略自动处理这种情况,推荐用Polly库实现:

首先安装Polly包:

Install-Package Polly

然后在迁移代码中添加重试逻辑:

using Polly;

// ... 后台任务中的迁移代码
var retryPolicy = Policy
    .Handle<Microsoft.Data.Sqlite.SqliteException>(ex => ex.Message.Contains("locked"))
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // 指数退避重试

await retryPolicy.ExecuteAsync(async () =>
{
    await dbContext.Database.MigrateAsync();
});

这样如果第一次迁移碰到锁异常,会自动重试3次,每次间隔时间翻倍,大概率能等到锁释放后成功执行。

4. 检查Release模式下的文件权限

虽然Debug和Release权限通常一致,但还是可以确认一下:应用池的运行身份是否对数据库文件所在目录(比如App_Data)有读写权限,避免因为权限问题导致迁移失败。

按照上面的步骤调整后,应该就能解决进程回收后的迁移异常问题了,我当时就是这么搞定的😉

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:33:54