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

EF Core运行时创建数据库后迁移失败,dotnet ef命令却正常

问题

应用首次启动时调用context.Database.Migrate(),仅能创建数据库,但迁移执行前抛出错误;多次尝试有时出现超时异常,有时迁移耗时超10分钟。但使用dotnet ef database update命令执行迁移完全正常。

复现环境

  • SQL Server版本:Microsoft SQL Server 2022 - 16.0.4105.2 Express Edition (64-bit) on Linux (Ubuntu 22.04.3 LTS)
  • EF Core相关包版本:
    Microsoft.EntityFrameworkCore 8.0.2
    Microsoft.EntityFrameworkCore.Design 8.0.2
    Microsoft.EntityFrameworkCore.SqlServer 8.0.2
    
  • dotnet-ef工具版本:8.0.2
  • 启动代码:
    using var context = scope.ServiceProvider.GetRequiredService<MyContext>();
    context.Database.Migrate();
    
  • 连接字符串所用SQL用户拥有sysadmin权限。
解决方案

以下是几种排查和解决的方向:

1. 调整命令超时时间

应用启动时的迁移命令超时可能过短,而dotnet ef工具默认的超时设置更长。可以在DbContext配置中显式设置迁移命令的超时时间:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(
        "<你的连接字符串>",
        sqlOptions => sqlOptions.CommandTimeout(120)); // 设置为120秒,可根据需求调整
}

同时,也可以在连接字符串中增加连接超时设置:

Server=<服务器地址>;Database=<数据库名>;User Id=<用户名>;Password=<密码>;Connect Timeout=60;

2. 添加数据库创建后的重试逻辑

SQL Server创建数据库后需要短暂的初始化时间,应用立即执行迁移可能引发连接问题。可以添加重试机制,在迁移失败时等待并重试:

using var scope = host.Services.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<MyContext>();

int retryCount = 3;
int delaySeconds = 5;
bool migrationSuccess = false;

while (retryCount > 0 && !migrationSuccess)
{
    try
    {
        context.Database.Migrate();
        migrationSuccess = true;
    }
    catch (SqlException)
    {
        retryCount--;
        if (retryCount > 0)
        {
            Thread.Sleep(TimeSpan.FromSeconds(delaySeconds));
            delaySeconds *= 2; // 指数退避
        }
    }
}

如果需要更健壮的重试,可引入Polly库实现策略。

3. 确认DbContext的生命周期与服务范围

确保在正确的服务范围内获取DbContext,且Host已完成构建。正确的启动顺序示例:

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
        services.AddDbContext<MyContext>(options =>
            options.UseSqlServer(context.Configuration.GetConnectionString("DefaultConnection")));
    })
    .Build();

// 需在Host构建完成后创建服务范围
using var scope = host.Services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<MyContext>();
dbContext.Database.Migrate();

host.Run();

4. 验证迁移脚本一致性

确认应用使用的迁移脚本与dotnet ef工具使用的一致。可尝试清理旧迁移并重新生成:

dotnet ef migrations remove
dotnet ef migrations add InitialCreate
dotnet ef database update

之后再测试应用启动时的迁移逻辑。

5. 排查SQL Server的阻塞与日志

检查SQL Server是否存在阻塞迁移的进程,可通过以下SQL查询:

-- 查询当前锁信息
SELECT resource_type, resource_database_id, request_mode, request_session_id
FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID('<你的数据库名>');

-- 查询当前执行请求
SELECT session_id, command, status, wait_type
FROM sys.dm_exec_requests
WHERE database_id = DB_ID('<你的数据库名>');

同时查看SQL Server的错误日志,排查是否存在数据库初始化相关的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:52:48