當您想要將多個工作系結在一起,以便以單一工作單位的形式執行時,會使用 ADO.NET 中的交易。 例如,假設應用程式會執行兩項工作。 首先,它會使用訂單資訊來更新數據表。 其次,它會更新包含庫存信息的數據表,扣除已訂購的商品。 如果任一任務失敗,則會回復這兩個更新。
判斷交易類型
當交易是單一階段交易且由資料庫直接處理時,交易會被視為本機交易。 當交易由交易監視器協調時,交易會被視為分散式交易,並使用安全機制(例如兩階段認可)來進行交易解析。
每個 .NET Framework 數據提供者都有自己的 Transaction 對象來執行本機交易。 如果您需要在 SQL Server 資料庫中執行交易,請選取 System.Data.SqlClient 交易。 針對 Oracle 交易,請使用 System.Data.OracleClient 提供者。 此外,還有一個 DbTransaction 類別可供撰寫需要交易的提供者獨立程序代碼。
備註
交易在伺服器上執行時最有效率。 如果您正在使用大量使用明確交易的 SQL Server 資料庫,請考慮使用 Transact-SQL BEGIN TRANSACTION 語句將其撰寫為預存程式。
透過單一連線執行交易
在 ADO.NET 中,您可以使用 Connection 物件來控制交易。 您可以使用 BeginTransaction 方法來開始本機交易。 一旦您開始進行交易,就可以使用Transaction物件的屬性Command,在該交易中登記命令。 然後,您可以根據交易的組成部分的成功或失敗結果,提交或回復資料來源所做的修改。
備註
EnlistDistributedTransaction方法不應該用於本地交易。
交易的範圍僅限於連線。 下列範例會執行由 區塊中 try 兩個不同的命令所組成的明確交易。 這些命令會針對 AdventureWorks SQL Server 範例資料庫中 Production.ScrapReason 數據表執行 INSERT 語句,如果未擲回任何例外狀況,則會認可這些語句。 若發生異常,區塊中的 catch 程式碼會回滾交易。 如果交易已中止,或在交易完成之前關閉連接,它就會自動回復。
範例
請遵循下列步驟來執行交易。
呼叫BeginTransaction物件的SqlConnection方法,以標記交易的開頭。 方法 BeginTransaction 返回交易的引用。 此參考會指派給 SqlCommand 在交易中登記的物件。
將
Transaction物件指派給 Transaction 的 SqlCommand 屬性以執行。 如果在與使用中交易的連線上執行命令,而且Transaction物件尚未指派給Transaction對象的 屬性Command,則會擲回例外狀況。執行必要的命令。
呼叫Commit方法,對SqlTransaction物件進行操作以完成交易,或呼叫Rollback方法來結束交易。 如果在Commit或Rollback方法執行之前關閉或處置連接,則會回滾交易。
下列程式代碼範例示範使用 ADO.NET 搭配 Microsoft SQL Server 的交易式邏輯。
using (SqlConnection connection = new(connectionString))
{
connection.Open();
// Start a local transaction.
SqlTransaction sqlTran = connection.BeginTransaction();
// Enlist a command in the current transaction.
SqlCommand command = connection.CreateCommand();
command.Transaction = sqlTran;
try
{
// Execute two separate commands.
command.CommandText =
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
command.ExecuteNonQuery();
command.CommandText =
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
command.ExecuteNonQuery();
// Commit the transaction.
sqlTran.Commit();
Console.WriteLine("Both records were written to database.");
}
catch (Exception ex)
{
// Handle the exception if the transaction fails to commit.
Console.WriteLine(ex.Message);
try
{
// Attempt to roll back the transaction.
sqlTran.Rollback();
}
catch (Exception exRollback)
{
// Throws an InvalidOperationException if the connection
// is closed or the transaction has already been rolled
// back on the server.
Console.WriteLine(exRollback.Message);
}
}
}
Using connection As New SqlConnection(connectionString)
connection.Open()
' Start a local transaction.
Dim sqlTran As SqlTransaction = connection.BeginTransaction()
' Enlist a command in the current transaction.
Dim command As SqlCommand = connection.CreateCommand()
command.Transaction = sqlTran
Try
' Execute two separate commands.
command.CommandText = _
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')"
command.ExecuteNonQuery()
command.CommandText = _
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')"
command.ExecuteNonQuery()
' Commit the transaction
sqlTran.Commit()
Console.WriteLine("Both records were written to database.")
Catch ex As Exception
' Handle the exception if the transaction fails to commit.
Console.WriteLine(ex.Message)
Try
' Attempt to roll back the transaction.
sqlTran.Rollback()
Catch exRollback As Exception
' Throws an InvalidOperationException if the connection
' is closed or the transaction has already been rolled
' back on the server.
Console.WriteLine(exRollback.Message)
End Try
End Try
End Using
另請參閱
- 交易和同時性
- 分散式交易
- System.Transactions 與 SQL Server 整合
- ADO.NET 概觀