我有一个 .NET 8 Web 应用程序,并且正在使用带有 Npgsql 8.0.1 的实体框架。
我正在使用
NpgsqlDataSourceBuilder
初始化多个数据库上下文,如 此处所述。
程序.cs
//DbContext 1
var applicationDataSourceBuilder = new NpgsqlDataSourceBuilder(builder.Configuration["ConnectionStrings:ApplicationConnection"]);
await using var applicationDataSource = applicationDataSourceBuilder.Build();
builder.Services.AddDbContext<ApplicationDbContext>(
options =>
{
options.UseNpgsql(applicationDataSource);
options.EnableSensitiveDataLogging(builder.Environment.IsDevelopment());
});
//DbContext 2
var otherDataSourceBuilder = new NpgsqlDataSourceBuilder(builder.Configuration["ConnectionStrings:OtherConnection"]);
otherDataSourceBuilder.UseNetTopologySuite();
await using var otherDataSource = otherDataSourceBuilder.Build();
builder.Services.AddDbContext<OtherDbContext>(
options =>
{
options.UseNpgsql(otherDataSource);
options.EnableSensitiveDataLogging(builder.Environment.IsDevelopment());
});
从实际运行应用程序时我可以看出,这工作得很好(但也许潜伏着一些我目前没有意识到的讨厌的东西!),但如果我尝试任何迁移,例如运行
Update-Database -Context ApplicationDbContext
,则会出现以下错误被抛出。
使用服务器上数据库“devapps”的连接时发生错误 'tcp://localhost:5432'.
System.ObjectDisposeException:无法访问已处置的对象。
对象名称:'Npgsql.PoolingDataSource'。
如果我切换
ApplicationDbContext
以使用这种初始化方式(即不使用 NpggqlDataSourceBuilder
)
builder.Services.AddDbContext<ApplicationDbContext>(
options =>
{
options.UseNpgsql("name=ConnectionStrings:ApplicationConnection");
options.EnableSensitiveDataLogging(builder.Environment.IsDevelopment());
});
它工作得很好,但我从文档中得到的印象是使用
NpgsqlDataSourceBuilder
是推荐的做事方式。
我得出的结论是,我一定是从根本上误解了使用 Npgsql 初始化多个数据库上下文的正确方法。
TL;博士
但是文档给我的印象是使用
是推荐的做事方式。NpgsqlDataSourceBuilder
不,请查看 Npgsql Entity Framework Core Provider 文档,尤其是 ASP.NET Core 应用程序的附加配置 部分,其中显示了 DI 示例(基本上是有效的):
services.AddDbContext<BloggingContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("BloggingContext")));
详情:
您有 using 声明:
// ...
await using var applicationDataSource = applicationDataSourceBuilder.Build();
// ...
await using var otherDataSource = otherDataSourceBuilder.Build();
// ...
这将在封闭方法/作用域的末尾处理两个数据源。我看到有两种可能性:
首先要尝试的是删除
using
:
var applicationDataSource = applicationDataSourceBuilder.Build();
var otherDataSource = otherDataSourceBuilder.Build();
看看一切是否正常。之后,根据实际代码和原因,如果第一个选项是原因,您可以修复问题,或者使用
EF.IsDesignTime
属性有条件地处置源。
没有重现 ATM 的设置来确定实际原因,也许稍后会尝试。