Created
October 23, 2015 18:09
-
-
Save vivmishra/1e7ddf47979f62fdd4a1 to your computer and use it in GitHub Desktop.
Sample for System.Transactions updates in .NET 4.6.1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Transactions; | |
namespace YourNamespaceGoesHere | |
{ | |
public class NonMSDTCPromoterEnlistment : IPromotableSinglePhaseNotification | |
{ | |
Guid promoterType; | |
Guid distributedTxId; | |
Transaction enlistedTransaction; | |
bool promoted; | |
public NonMSDTCPromoterEnlistment(Guid promoterType) | |
{ | |
this.promoterType = promoterType; | |
this.distributedTxId = Guid.Empty; | |
this.enlistedTransaction = null; | |
this.promoted = false; | |
} | |
// This is a method that a program would call to create a Promotable Single Phase Enlistment on the specified | |
// transaction. If no parameter is passed or null is passed, Transaction.Current is used. | |
public bool Enlist(Transaction txToEnlist = null) | |
{ | |
if (txToEnlist == null) | |
{ | |
txToEnlist = Transaction.Current; | |
} | |
// Attempt to create the Promotable Single Phase Enlistment with the promoter type specified to the constructor. | |
if (txToEnlist.EnlistPromotableSinglePhase(this, this.promoterType)) | |
{ | |
// We have successfully created the promotable single phase enlistment with System.Transactions. | |
// This is where you would do the work to do the single phase enlistment with the resource manager. | |
// How that is done is beyond the scope of this sample. | |
// RM.SinglePhaseEnlist(...); | |
} | |
else | |
{ | |
// There is either already a promotable single phase enlistment on the transaction, or the transaction | |
// is already promoted. You can return false and let the caller decide what to do. | |
return false; | |
// Or you can check to see if the promoter type for the transaction matches the promoter type provided in | |
// the constructor and if it does, tell the resource manager to enlist directly with the non-MSDTC transaction manager identified | |
// by that promoter type. The work to do that enlistment is beyond the scope of this sample. | |
// if (this.promoterType == txToEnlist.PromoterType) | |
// { | |
// // Get the promoted token from the transaction. This will cause | |
// // promotion if it is not already promoted. | |
// byte[] promotedToken = txToEnlist.PromotedToken; | |
// RM.EnlistDistributed(..., promotedToken, ...); | |
// } | |
} | |
// If we get here, we have successfully enlisted, so remember the transaction for later use. | |
this.enlistedTransaction = txToEnlist; | |
return true; | |
} | |
// This is the implementation of IPromotableSinglePhaseNotification.Initialize, which is called by | |
// System.Transactions when Transaction.EnlistPromotableSinglePhase is called. | |
public void Initialize() | |
{ | |
// Perform any initialization work for the enlistment here. | |
return; | |
} | |
// This is the implementation of the IPromotableSinglePhaseNotification.Rollback method. | |
public void Rollback(SinglePhaseEnlistment singlePhaseEnlistment) | |
{ | |
if (this.promoted) | |
{ | |
// This is where you would need to tell the non-MSDTC transaction manager to rollback the transaction. | |
// How that is done is beyond the scope of this sample. | |
// TxMgr.Rollback(..., this.distributedTxId, ...); | |
} | |
else | |
{ | |
// This is where you would tell the resource manager to rollback. | |
// How that is done is beyond the scope of this sample. | |
// RM.Rollback(...); | |
} | |
singlePhaseEnlistment.Done(); | |
} | |
// This is the implementation of the IPromotableSinglePhaseNotification.SinglePhaseCommit method. | |
public void SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment) | |
{ | |
TransactionStatus commitResponse; | |
if (this.promoted) | |
{ | |
// This is where you would tell the non-MSDTC transaction manager to | |
// commit the transaction. How that is done is beyond the scope of this sample. | |
// commitResponse = TxMgr.Commit(..., this.distributedTxId, ...); | |
} | |
else | |
{ | |
// This is where you would tell the resource manager to | |
// perform a SinglePhaseCommit because they are the only resource manager involved in the transaction. | |
// How that is done is beyond the scope of this sample. | |
// commitResponse == RM.SinglePhaseCommit(...); | |
} | |
switch (commitResponse) | |
{ | |
case TransactionStatus.Committed: | |
{ | |
singlePhaseEnlistment.Committed(); | |
break; | |
} | |
case TransactionStatus.Aborted: | |
{ | |
singlePhaseEnlistment.Aborted(new ApplicationException("Aborted by NonMSDTCPromoterEnlistment.SinglePhaseCommit")); | |
break; | |
} | |
case TransactionStatus.InDoubt: | |
{ | |
singlePhaseEnlistment.InDoubt(new ApplicationException("InDoubt by NonMSDTCPromoterEnlistment.SinglePhaseCommit")); | |
break; | |
} | |
default: | |
{ | |
throw new ApplicationException("InDoubt by NonMSDTCPromoterEnlistment.SinglePhaseCommit because of invalid TransactionStatus outcome value."); | |
} | |
} | |
} | |
// This is the implementation of the IPromotableSinglePhaseNotification.Promote method, which comes from the ITransactionPromoter derivation. | |
public byte[] Promote() | |
{ | |
byte[] promotedToken; | |
// This is where you would tell the non-MSDTC transaction manager to create a distributed transaction. | |
// This call needs to give you back the id of the distributed transaction (assuming it is a Guid) and the byte[] | |
// promoted token that can be used by resource managers to directly enlist with the distributed transaction manager. | |
// How that is done is beyond the scope of this sample. | |
// this.distributedTxId = TxMgr.CreateTransaction(..., out promotedToken, ...); | |
this.promoted = true; | |
// We now need to tell the resource manager to modify its enlistment to be with the distributed transaction manager | |
// instead of just being a SinglePhase enlistment. How that is done is beyond the scope of this sample. | |
// RM.PromoteEnlistment(..., promotedToken, ...); | |
// We need to set the distributed transaction id on the Transaction. This MUST be done inside this Promote method. | |
// Note that we are passing "this" as the promotableSinglePhaseNotification parameter because that is what was | |
// passed to Transaction.EnlistPromotableSinglePhase in the Enlist method above. | |
this.enlistedTransaction.SetDistributedTransactionId(this, this.distributedTxId); | |
return promotedToken; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment