Npgsql提供程序是否支持TransactionScope?

Fed*_*ini 6 npgsql

我正在尝试与Npgsql提供程序一起使用TransactionScope。我在一个古老的问题(.net中的PostgreSQL提供程序,支持TransactionScope)中发现Npgsql还不支持它。现在,大约5年后,Npgsql是否支持TransactionScope?我使用Npgsql 3.0.3并使用以下代码对自己进行了测试:

using (var scope = new TransactionScope())
{
    using(var connection = new Npgsql.NpgsqlConnection("server=localhost;user id=*****;password=*****database=test;CommandTimeout=0"))
    {
        connection.Open();

        var command = new NpgsqlCommand(@"insert into test.table1 values ('{10,20,30}', 2);");
        command.Connection = connection;
        var result = command.ExecuteNonQuery();

        // scope.Complete();  <-- Not committed
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以确认Npgsql不支持TransactionScope吗?

编辑#1 确认Npgsql对TransactionScope的支持后,我发现您需要确保在PostgreSQL配置中启用了分布式事务,请检查postgres.conf文件中的max_prepared_transactions参数(记住要重新启动服务器) 。

编辑#2 我在服务器上启用了分布式事务,但是现在在使用TransactionScope和Npgsql时出现错误。这是我的代码:

using (var sourceDbConnection = new NpgsqlConnection(SourceConnectionString))
using (var destinationDbConnection = new NpgsqlConnection(DestinationConnectionString))
using (var scope = new TransactionScope())
    {
        sourceDbConnection.Open();
        destinationDbConnection.Open();

        Logger.Info("Moving data for the {0} table.", TableName.ToUpper());
        var innerStopWatch = new Stopwatch();
        innerStopWatch.Start();

        foreach (var entity in entities)
        {
            var etlEntity = new EtlInfoItem
            {
                MigratedEntityId = category.RowId,
                ProjectId = category.ProjectId,
                ExecutionDatetime = DateTime.Now
            };

            // Insert into the destination database
            var isRowMigrated = InsertEntity(entity, DestinationSchema, destinationDbConnection);

            if (isRowMigrated)
            {
                // Update the ETL migration table
                InsertCompletedEtlMigrationEntity(etlEntity, EtlSchema, sourceDbConnection);
            }
            else
            {
                // Update the ETL migration table
                InsertFailedEtlMigrationEntity(etlEntity, EtlSchema, sourceDbConnection);
            }
        }

        Logger.Info("Data moved in {0} sec.", innerStopWatch.Elapsed);

        Logger.Info("Committing transaction to the source database");
                innerStopWatch.Restart();

        scope.Complete();

        innerStopWatch.Stop();
        Logger.Info("Transaction committed in {0} sec.", innerStopWatch.Elapsed);
    }
Run Code Online (Sandbox Code Playgroud)

当TransactionScope从范围中退出时(退出using语句时),我得到一个带有以下堆栈跟踪的Null引用异常:服务器堆栈跟踪:在Npgsql.NpgsqlConnector.Cleanup()在Npgsql.NpgsqlConnector.Break()在Npgsql。 Npgsql.NpgsqlConnector.ReadExpectingT上的NpgsqlConnector.ReadSingleMessage(DataRowLoadingMode dataRowLoadingMode,Boolean returnNullForAsyncMessage).........它是随机发生的。

Sha*_*sky 6

Npgsql确实支持TransactionScope,并且已经支持了很长一段时间。但是,至少就目前而言,为了使您的连接参与TransactionScope,您必须:

  1. 包括Enlist=true在您的连接字符串中,或
  2. 呼叫NpgsqlConnection.EnlistTransaction

看一下有关此示例的Npgsql单元测试

  • 对于新访客,这不再是必需的,因为它现在是默认设置 (4认同)