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

如何为Blazor Server应用的EF Core多数据库提供程序创建迁移并运行时配置?

一、解决多数据库迁移创建问题

1. 修正迁移命令与项目配置

你的核心问题是迁移命令参数使用错误,以及启动项目选择不当。正确操作如下:

  • 必须将主项目SportsOrganizer.Server设为启动项目,EF Core需要读取启动项目的配置来识别ApplicationDbContext,而非SportsOrganizer.Models项目。
  • 每个迁移项目需单独指定数据库提供程序,并明确上下文所在项目。

针对各数据库的迁移命令示例:

SqlServer

Add-Migration InitialCreate -Project SportsOrganizer.SqlServer -StartupProject SportsOrganizer.Server -Context ApplicationDbContext -Args "--provider Microsoft.EntityFrameworkCore.SqlServer"

MySql(Pomelo驱动)

Add-Migration InitialCreate -Project SportsOrganizer.MySql -StartupProject SportsOrganizer.Server -Context ApplicationDbContext -Args "--provider Pomelo.EntityFrameworkCore.MySql"

Sqlite

Add-Migration InitialCreate -Project SportsOrganizer.Sqlite -StartupProject SportsOrganizer.Server -Context ApplicationDbContext -Args "--provider Microsoft.EntityFrameworkCore.Sqlite"

Oracle

Add-Migration InitialCreate -Project SportsOrganizer.Oracle -StartupProject SportsOrganizer.Server -Context ApplicationDbContext -Args "--provider Oracle.EntityFrameworkCore"

PostgreSql

Add-Migration InitialCreate -Project SportsOrganizer.PostgreSql -StartupProject SportsOrganizer.Server -Context ApplicationDbContext -Args "--provider Npgsql.EntityFrameworkCore.PostgreSQL"

2. 迁移项目依赖检查

  • 每个迁移项目(如SportsOrganizer.SqlServer)必须引用SportsOrganizer.Models项目,确保能访问ApplicationDbContext。
  • 每个迁移项目的.csproj文件中,需安装对应数据库的EF Core NuGet包(比如SqlServer项目装Microsoft.EntityFrameworkCore.SqlServer),避免依赖缺失。

二、运行时应用迁移与DbContext注册方案

1. 动态注册DbContext

在Program.cs中跳过硬编码注册,先检查配置是否存在有效数据库信息:

var builder = WebApplication.CreateBuilder(args);

// 读取临时配置的数据库信息(可来自设置页面提交的存储)
var dbProvider = builder.Configuration.GetValue<string>("Database:Provider");
var connectionString = builder.Configuration.GetValue<string>("Database:ConnectionString");

if (string.IsNullOrEmpty(dbProvider) || string.IsNullOrEmpty(connectionString))
{
    // 注册设置页面所需服务
    builder.Services.AddRazorPages();
    builder.Services.AddServerSideBlazor();
}
else
{
    // 根据提供程序动态注册DbContext
    switch (dbProvider.ToLower())
    {
        case "sqlserver":
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(connectionString));
            break;
        case "mysql":
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
                options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));
            break;
        case "sqlite":
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlite(connectionString));
            break;
        case "oracle":
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
                options.UseOracle(connectionString));
            break;
        case "postgresql":
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
                options.UseNpgsql(connectionString));
            break;
        default:
            throw new InvalidOperationException("不支持的数据库提供程序");
    }

    // 注册常规业务服务
    builder.Services.AddRazorPages();
    builder.Services.AddServerSideBlazor();
}

var app = builder.Build();

// 仅当配置有效时应用迁移
if (!string.IsNullOrEmpty(dbProvider) && !string.IsNullOrEmpty(connectionString))
{
    using var scope = app.Services.CreateScope();
    var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
    dbContext.Database.Migrate();
}

// 中间件配置
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.MapBlazorHub();
// 未配置数据库时默认跳转设置页面
app.MapFallbackToPage(string.IsNullOrEmpty(dbProvider) ? "/Setup" : "/_Host");

app.Run();

2. 设置页面实现要点

  • 创建Setup.razor页面,提供数据库提供程序下拉选择、连接字符串输入表单。
  • 用户提交后,将配置写入appsettings.json(通过IConfigurationRoot的Save方法)或内存缓存。
  • 配置保存后,调用IHostApplicationLifetime.StopApplication()触发应用重启,使新配置生效。

3. 关键注意事项

  • 确保应用进程对目标数据库有足够权限执行迁移(如创建表、修改结构)。
  • 配置持久化必须可靠,避免重启后丢失设置。
  • 在迁移和注册逻辑中添加异常捕获,处理连接失败、迁移错误等场景,返回用户友好提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:37:47