將資源登記成為交易中的參與者
參與交易的每項資源都會受到資源管理員的管理,而這些資源管理員在採取行動時必須經過交易管理員的協調。 訂閱者透過交易管理員登記到交易中,並收到告知來完成整個協調程序。
本主題將涵蓋如何在交易中登記資源 (或多項資源),以及登記的型別有哪些。 在單一階段和多重階段中認可交易主題涵蓋如何在登錄的資源之間協調交易認可。
將資源登記到交易中
為了讓資源參與交易,資源必須登記到交易中。 Transaction 類別會定義一組提供這個功能的方法,其名稱開頭為 Enlist。 不同的 Enlist 方法會對應至資源管理員可能具有的不同類型登錄。 具體來說,您可以使用變動性資源的 EnlistVolatile 方法,以及永久性資源的 EnlistDurable 方法。 資源管理員的永久性 (反之為變動性) 指的是資源管理員是否支援故障復原。 如果資源管理員支援故障復原,會在第一階段 (準備階段) 將資料保存在永久性儲存裝置中。這樣一來,如果資源管理員故障,資料就可以在復原後重新登記到交易中,並依據接收自 TM 的告知執行適當的動作。 一般來說,變動性資源管理員會將變動性資源當成記憶體中的資料結構來管理 (例如,記憶體中的交易雜湊表),而永久性資源管理員則會管理具有較持久之備份存放區的資源 (例如,使用磁碟做為備份存放區的資料庫)。
在依據資源永久性支援來決定是否採用 EnlistDurable 或 EnlistVolatile 方法之後,為了方便作業,您應該實作資源管理員的 IEnlistmentNotification 介面,以便登記資源並讓其參與兩階段交易認可 (2PC)。 如需 2PC 的詳細資訊,請參閱在單一階段和多重階段中認可交易。
單一參與者可藉由呼叫 EnlistDurable 與 EnlistVolatile 數次為一個以上的這類通訊協定進行登記。
永久性登記
您可以使用 EnlistDurable 方法來登記資源管理員,以便以永久性資源身分參與交易。 如果永久性資源管理員在交易中途停機,預期它會重新登記 (使用 Reenlist 方法) 到所有已參與但未完成第二階段的交易中,並於重新上線後執行復原。一旦完成復原程序,資源管理員便會呼叫 RecoveryComplete。 如需復原的詳細資訊,請參閱執行復原。
所有 EnlistDurable 方法都會將 Guid 物件當成第一個參數。 交易管理員會使用 Guid,將永久性登記與特定的資源管理員關聯在一起。 這麼一來,資源管理員在重新啟動時就必須持續使用相同的 Guid 來辨識自己 (即使是在不同的資源管理員之間亦然),否則復原會失敗。
EnlistDurable 方法的第二個參數會參考某個資源管理員實作以接收交易告知的物件。 您會使用多載來告知交易管理員有關資源管理員是否支援單一階段交易認可 (SPC) 最佳化。 在大部分情況下,您應該實作 IEnlistmentNotification介面來參與兩階段交易認可 (2PC)。 但是,如果您希望最佳化交易認可處理序,則可以考慮實作 SPC 的 ISinglePhaseNotification 介面。 如需 SPC 的詳細資訊,請參閱在單一階段和多重階段中認可交易和使用單一階段交易認可和可提升單一階段通知進行最佳化。
第三個參數是一種 EnlistmentOptions 列舉型別,其值可為 None 或 EnlistDuringPrepareRequired。 如果將值設為 EnlistDuringPrepareRequired,登記作業可能會在收到來自交易管理員的準備告知時登記額外的資源管理員。 但是,您應該了解這種登記型別不適用於單一階段交易認可最佳化作業。
變動性登記
管理快取之類的變動性資源的參與者,應該使用 EnlistVolatile 方法來登記。 此類物件也許無法取得交易結果,或是在系統故障後復原所參與的任何交易狀態。
如同先前所述,如果資源管理員負責管理記憶體中的變動性資源,就需要進行變動性登記作業。 使用 EnlistVolatile 的其中一項好處就是,它不會強制擴大不必要的交易規模。 如需交易擴大範圍的詳細資訊,請參閱交易管理擴大規模主題。 登錄變動性意指交易管理員處理登錄的方式有何差異,以及交易管理員對資源管理員有何期待。 這是因為變動性資源管理員無法執行復原。 EnlistVolatile 方法不會使用 Guid 參數,因為變動性資源管理員無法執行復原,也無法呼叫需要 Reenlist 的 Guid 方法。
有關永久性登記方面,不管您使用哪種多載方法來登記,都會向交易管理員表示您的資源管理員是否支援單一階段交易認可最佳化。 由於變動性資源管理員無法執行復原,因此準備階段期間不會針對變動性登記寫入復原資訊。 如此一來,呼叫 RecoveryInformation 方法將產生 InvalidOperationException 的結果。
下列範例會顯示如何使用 EnlistVolatile 方法將此類物件登記為交易中的參與者。
static void Main(string[] args)
{
try
{
using (TransactionScope scope = new TransactionScope())
{
//Create an enlistment object
myEnlistmentClass myEnlistment = new myEnlistmentClass();
//Enlist on the current transaction with the enlistment object
Transaction.Current.EnlistVolatile(myEnlistment, EnlistmentOptions.None);
//Perform transactional work here.
//Call complete on the TransactionScope based on console input
ConsoleKeyInfo c;
while(true)
{
Console.Write("Complete the transaction scope? [Y|N] ");
c = Console.ReadKey();
Console.WriteLine();
if ((c.KeyChar == 'Y') || (c.KeyChar == 'y'))
{
scope.Complete();
break;
}
else if ((c.KeyChar == 'N') || (c.KeyChar == 'n'))
{
break;
}
}
}
}
catch (System.Transactions.TransactionException ex)
{
Console.WriteLine(ex);
}
catch
{
Console.WriteLine("Cannot complete transaction");
throw;
}
}
class myEnlistmentClass : IEnlistmentNotification
{
public void Prepare(PreparingEnlistment preparingEnlistment)
{
Console.WriteLine("Prepare notification received");
//Perform transactional work
//If work finished correctly, reply prepared
preparingEnlistment.Prepared();
// otherwise, do a ForceRollback
preparingEnlistment.ForceRollback();
}
public void Commit(Enlistment enlistment)
{
Console.WriteLine("Commit notification received");
//Do any work necessary when commit notification is received
//Declare done on the enlistment
enlistment.Done();
}
public void Rollback(Enlistment enlistment)
{
Console.WriteLine("Rollback notification received");
//Do any work necessary when rollback notification is received
//Declare done on the enlistment
enlistment.Done();
}
public void InDoubt(Enlistment enlistment)
{
Console.WriteLine("In doubt notification received");
//Do any work necessary when in doubt notification is received
//Declare done on the enlistment
enlistment.Done();
}
}
Public Shared Sub Main()
Try
Using scope As TransactionScope = New TransactionScope()
'Create an enlistment object
Dim myEnlistmentClass As New EnlistmentClass
'Enlist on the current transaction with the enlistment object
Transaction.Current.EnlistVolatile(myEnlistmentClass, EnlistmentOptions.None)
'Perform transactional work here.
'Call complete on the TransactionScope based on console input
Dim c As ConsoleKeyInfo
While (True)
Console.Write("Complete the transaction scope? [Y|N] ")
c = Console.ReadKey()
Console.WriteLine()
If (c.KeyChar = "Y") Or (c.KeyChar = "y") Then
scope.Complete()
Exit While
ElseIf ((c.KeyChar = "N") Or (c.KeyChar = "n")) Then
Exit While
End If
End While
End Using
Catch ex As TransactionException
Console.WriteLine(ex)
Catch
Console.WriteLine("Cannot complete transaction")
Throw
End Try
End Sub
End Class
Public Class EnlistmentClass
Implements IEnlistmentNotification
Public Sub Prepare(ByVal myPreparingEnlistment As PreparingEnlistment) Implements System.Transactions.IEnlistmentNotification.Prepare
Console.WriteLine("Prepare notification received")
'Perform transactional work
'If work finished correctly, reply with prepared
myPreparingEnlistment.Prepared()
End Sub
Public Sub Commit(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Commit
Console.WriteLine("Commit notification received")
'Do any work necessary when commit notification is received
'Declare done on the enlistment
myEnlistment.Done()
End Sub
Public Sub Rollback(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Rollback
Console.WriteLine("Rollback notification received")
'Do any work necessary when rollback notification is received
'Declare done on the enlistment
myEnlistment.Done()
End Sub
Public Sub InDoubt(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.InDoubt
Console.WriteLine("In doubt notification received")
'Do any work necessary when in doubt notification is received
'Declare done on the enlistment
myEnlistment.Done()
End Sub
End Class
最佳化效能
Transaction 類別也會提供 EnlistPromotableSinglePhase 方法,以便登記可提升單一階段登記 (PSPE)。 這樣一來永久性資源管理員 (RM) 就可以裝載並「擁有」交易,並可在稍後視需要將規模擴大為由 MSDTC 管理。 如需此情況的詳細資訊,請參閱使用單一階段認可和可提升單一階段通知進行最佳化。