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

使用Npgsql初始化多DbContext导致EF迁移失败的问题

解决Npgsql DataSource多DbContext迁移时的已释放对象错误

问题根源

迁移工具的服务生命周期与应用运行时不同,若NpgsqlDataSource未以单例模式注册,会在迁移过程中被提前释放,触发ObjectDisposedException。直接传连接字符串时EF会自动管理连接源,因此迁移正常,但不符合Npgsql 8.x的最佳实践。

正确实现步骤

1. 单例注册NpgsqlDataSource

根据两个DbContext对应的数据库,注册全局复用的DataSource实例:

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// 注册ApplicationDb对应的DataSource(默认实例)
builder.Services.AddNpgsqlDataSource(builder.Configuration.GetConnectionString("ApplicationDb"));

// 注册OtherDb对应的DataSource(命名实例,区分不同库)
builder.Services.AddNpgsqlDataSource(
    builder.Configuration.GetConnectionString("OtherDb"),
    name: "OtherDbDataSource");

2. 配置DbContext注入对应DataSource

为每个DbContext配置时,从服务容器中获取已注册的DataSource:

// 配置ApplicationDbContext
builder.Services.AddDbContext<ApplicationDbContext>((sp, options) =>
{
    var dataSource = sp.GetRequiredService<NpgsqlDataSource>();
    options.UseNpgsql(dataSource);
});

// 配置OtherDbContext(使用命名DataSource)
builder.Services.AddDbContext<OtherDbContext>((sp, options) =>
{
    var dataSource = sp.GetRequiredService<NpgsqlDataSource>("OtherDbDataSource");
    options.UseNpgsql(dataSource);
});

3. (可选)添加设计时工厂确保迁移兼容性

若迁移工具仍报错,为DbContext添加设计时工厂,手动创建DataSource避免服务容器的生命周期问题:

public class ApplicationDbContextDesignTimeFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
{
    public ApplicationDbContext CreateDbContext(string[] args)
    {
        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();

        var dataSource = new NpgsqlDataSourceBuilder(config.GetConnectionString("ApplicationDb"))
            .Build();

        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseNpgsql(dataSource)
            .Options;

        return new ApplicationDbContext(options);
    }
}

关键注意事项

  • NpgsqlDataSource是线程安全的连接池管理对象,必须以Singleton生命周期注册,避免重复创建和过早释放。
  • 多DbContext对应不同数据库时,需用命名DataSource区分,避免注入混淆。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:32:49