Npgsql 的多个数据库上下文导致迁移失败

问题描述 投票:0回答:1

我有一个 .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 初始化多个数据库上下文的正确方法。

c# .net-core entity-framework-core npgsql
1个回答
0
投票

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();
// ...

这将在封闭方法/作用域的末尾处理两个数据源。我看到有两种可能性:

  1. 您已将此代码移至某种方法,该方法会导致退出时处理数据源
  2. EF Core 工具使用一些肮脏的魔法来初始化上下文和连接,并使用提供的设置来运行 update database 命令,似乎这种魔法导致了 using 的包含范围,从而导致了您所看到的行为。

首先要尝试的是删除

using

var applicationDataSource = applicationDataSourceBuilder.Build();
var otherDataSource = otherDataSourceBuilder.Build();

看看一切是否正常。之后,根据实际代码和原因,如果第一个选项是原因,您可以修复问题,或者使用

EF.IsDesignTime
属性有条件地处置源。

没有重现 ATM 的设置来确定实际原因,也许稍后会尝试。

© www.soinside.com 2019 - 2024. All rights reserved.