When assigning an NpgsqlTransaction that has already been committed or rolled back to a NpgsqlCommand, the command executes without exception – but the transaction is silently ignored. This leads to the command being executed outside of any transaction, which is very dangerous and non-obvious.
Repro:
await using var conn = new NpgsqlConnection(...);
await conn.OpenAsync();
var tx = await conn.BeginTransactionAsync();
await tx.RollbackAsync(); // or CommitAsync()
var cmd = conn.CreateCommand();
cmd.Transaction = tx;
cmd.CommandText = "INSERT INTO test_table (value) VALUES ('oops')";
await cmd.ExecuteNonQueryAsync(); // Executes, but silently outside of transaction!
Expected behavior:
Throw an InvalidOperationException if the transaction has already been completed, or
At least log or document this behavior clearly.
Environment:
Npgsql version: 5.0.10
PostgreSQL version: 13.2
.NET version: .net core 6