適用於: .NET Framework
.NET
.NET 標準
當您想要將多個工作繫結在一起,使其以單一工作單位的形式執行時,將會使用 ADO.NET 中的交易。 例如,想像應用程式正在執行兩項工作。 首先,它會更新包含訂單資訊的資料表。 其次,它會更新包含庫存資訊的資料表,扣除已訂購的品項數量。 如果任一作業失敗,則兩項更新都會回復。
判斷交易類型
當交易為單一階段交易,且直接由資料庫處理時,系統便會將該交易視為本機交易。 當交易由交易監視器進行協調,並使用保全機制 (如兩階段交易認可) 進行交易解析時,系統便會將該交易視為分散式交易。
Microsoft SqlClient Data Provider for SQL Server 有自己的 SqlTransaction 物件,可在 SQL Server 資料庫中執行本機交易。 其他的 .NET 資料提供者也會提供自己的 Transaction 物件。 此外,還有一個 DbTransaction 類別可用於撰寫獨立於提供者以外且需要交易的程式碼。
注意
交易在伺服器上執行時效率最高。 如果您使用的 SQL Server 資料庫大量使用明確的異動,請考慮使用 Transact-SQL BEGIN TRANSACTION 陳述式,將它們寫入為預存程序。
使用單一連線執行交易
在 ADO.NET 中,您可以使用 Connection 物件控制交易。 您可以使用 BeginTransaction 方法來啟動本機交易。 開始異動之後,您可使用 Transaction 物件的 Command 屬性,在該異動中登記命令。 然後,您可以根據交易各元件的成功或失敗,提交或回復在資料來源所做的修改。
注意
EnlistDistributedTransaction 方法不可用於本機異動。
交易的範圍僅限於連接。 下列範例執行由 try 區塊中的兩個單獨命令所組成的明確異動。 指令會對 AdventureWorks SQL Server 範例資料庫中的 INSERT 資料表執行 Production.ScrapReason 陳述式;若未擲回任何例外狀況,這些陳述式便會提交。
catch 區塊中的程式碼會在擲回例外時回復該交易。 如果異動在完成之前遭到中止或連接關閉,則會自動復原該異動。
範例
請遵循下列步驟來執行異動。
呼叫 BeginTransaction 物件的 SqlConnection 方法,來標記交易的開始。 BeginTransaction 方法會傳回交易的參考。 此參考會指派給登記在交易中的 SqlCommand 物件。
將
Transaction物件指派給要執行之 Transaction 的 SqlCommand 屬性。 如果在具有作用中交易的連線上執行命令,且尚未將Transaction物件指派給Transaction物件的Command屬性,則會擲回例外狀況。執行必要的命令。
呼叫 Commit 物件的 SqlTransaction 方法來完成交易,或呼叫 Rollback 方法來中止交易。 如果在執行 Commit 或 Rollback 方法之前關閉或處置連接,則會復原異動。
下列程式碼範例將示範使用 Microsoft SqlClient Data Provider for SQL Server 的交易邏輯。
using System;
using Microsoft.Data.SqlClient;
class Program
{
static void Main(string[] args)
{
string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = AdventureWorks";
using (SqlConnection connection = new SqlConnection(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);
}
}
}
}
}