Я пытаюсь использовать TransactionScope с поставщиком Npgsql. Я нашел в старом вопросе (provider for PostgreSQL in .net with support for TransactionScope), что Npgsql еще не поддерживал его. Теперь, примерно через 5 лет, поддерживает ли Npgsql TransactionScope? Я сделал тест для себя, используя Npgsql 3.0.3 и используя следующий код:У провайдера Npgsql есть поддержка TransactionScope?
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
}
}
Любой может подтвердить, что Npgsql не поддерживает TransactionScope?
EDIT # 1 После подтверждения поддержки Npgsql к TransactionScope, я обнаружил, что вы должны быть уверены, что haev Distribuited транзакции включены в конфигурации PostgreSQL, проверяя max_prepared_transactions параметра в Postgres .conf (не забудьте перезагрузить сервер).
EDIT # 2 Я включил Сделку Distribuited на моем сервере, но теперь я получил сообщение об ошибке с помощью 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);
}
Когда TransactionScope выходит из области видимости (при выходе из используя заявление), я получаю пустую ссылку Exception со следующей трассировки стека: сервера трассировки стека: в Npgsql.NpgsqlConnector .Cleanup() в Npgsql.NpgsqlConnector.Break() в Npgsql.NpgsqlConnector.ReadSingleMessage (DataRowLoadingMode dataRowLoadingMode, Boolean returnNullForAsyncMessage) в Npgsql.NpgsqlConnector.ReadExpectingT ......... Это происходит случайным образом.
В моих тестах это не требует ненулевых * max_prepared_transactions *. У меня есть работа (передача параметра refcursor из одной команды в другую) с использованием 'Enlist = true' в строке соединения с * max_prepared_transactions * в ноль. –