Roadmap › ADO.NET — Connected & Disconnected Data Access › Module: Transactions, Pooling and Performance
Lessons in this course (9)
6. Transactions
Intermediate★ Must knowLesson 6 of 9
csharp
await using var conn = new SqlConnection(cs);
await conn.OpenAsync();
await using var tx = (SqlTransaction)await conn.BeginTransactionAsync(IsolationLevel.ReadCommitted);
try
{
var debit = new SqlCommand("UPDATE Accounts SET Balance = Balance - @amt WHERE Id = @from AND Balance >= @amt", conn, tx);
debit.Parameters.Add("@amt", SqlDbType.Decimal).Value = amount;
debit.Parameters.Add("@from", SqlDbType.Int).Value = fromId;
if (await debit.ExecuteNonQueryAsync() != 1) throw new InvalidOperationException("Insufficient funds");
var credit = new SqlCommand("UPDATE Accounts SET Balance = Balance + @amt WHERE Id = @to", conn, tx);
credit.Parameters.Add("@amt", SqlDbType.Decimal).Value = amount;
credit.Parameters.Add("@to", SqlDbType.Int).Value = toId;
await credit.ExecuteNonQueryAsync();
await tx.CommitAsync();
}
catch
{
await tx.RollbackAsync();
throw;
}TransactionScope (System.Transactions) gives ambient transactions across multiple connections/resources: create with TransactionScopeAsyncFlowOption.Enabled for async code; it can escalate to a distributed transaction (MSDTC) if several connections are involved — avoid that in cloud apps.