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

.NET 6中PostgreSQL连接池配合Transaction Scope失效问题求助

问题:TransactionScope中使用Npgsql+Dapper触发预准备事务禁用错误

问题描述

在.NET 6应用中使用Npgsql和Dapper连接PostgreSQL,连接字符串已启用连接池,所有命令在TransactionScope内执行,每次通过NpgsqlDataSource.OpenConnection新建连接。调用transactionScope.Complete()时抛出错误:

System.Transactions.TransactionAbortedException : 事务已中止。
---- Npgsql.PostgresException : 55000: prepared transactions are disabled

原本期望连接池会复用同一个连接,避免触发分布式事务,但实际不符合预期,需排查问题。

代码示例

using (var transactionScope = new TransactionScope()) 
{ 
   using connection1 = NpgsqlConnection();
    await connection1.ExecuteAsync("procedure1"); 
    using connection2 = NpgsqlConnection();
    await connection2.ExecuteAsync("procedure2");
    transactionScope.Complete();
}

private static NpgsqlConnection NpgsqlConnection()
{
    string connectionString = "User ID=postgres;Password=*****;Host=hostName;Port=5432;Database=DBTestPostgres;Pooling=true;";
    NpgsqlDataSourceBuilder dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
    using NpgsqlDataSource dataSource = dataSourceBuilder.Build();
    NpgsqlConnection conn = dataSource.OpenConnection();
    return conn;
}

错误原因

核心问题在于每次创建连接时都新建并释放NpgsqlDataSource实例。Npgsql的连接池与NpgsqlDataSource绑定,每个DataSource拥有独立的连接池。你在NpgsqlConnection()方法中每次创建新的DataSource并立即释放,导致每次获取的连接属于不同的连接池,完全无法复用。

当TransactionScope内打开第二个连接时,由于两个连接分属不同连接池,Npgsql无法复用同一连接,只能将事务升级为分布式事务。而PostgreSQL默认禁用预准备事务,因此抛出错误。

解决方案

1. 复用NpgsqlDataSource实例

NpgsqlDataSource是线程安全的,应作为单例在应用生命周期内复用,而非每次创建连接时新建。修改后的代码如下:

// 全局复用的DataSource实例,应用启动时初始化一次
private static readonly NpgsqlDataSource _dataSource;

static YourClassName()
{
    string connectionString = "User ID=postgres;Password=*****;Host=hostName;Port=5432;Database=DBTestPostgres;Pooling=true;";
    NpgsqlDataSourceBuilder dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
    _dataSource = dataSourceBuilder.Build();
}

private static NpgsqlConnection NpgsqlConnection()
{
    return _dataSource.OpenConnection();
}

// 原TransactionScope代码补充异步流支持
using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 
{ 
   using var connection1 = NpgsqlConnection();
    await connection1.ExecuteAsync("procedure1"); 
    using var connection2 = NpgsqlConnection();
    await connection2.ExecuteAsync("procedure2");
    transactionScope.Complete();
}

2. 关键补充说明

  • 必须为TransactionScope添加TransactionScopeAsyncFlowOption.Enabled参数,否则异步方法会破坏事务上下文。
  • 若确需使用分布式事务,需在PostgreSQL配置文件postgresql.conf中设置max_prepared_transactions为大于0的值(如100),但这并非最优解,复用连接池才是符合设计预期的做法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 17:37:17