¿Cómo me inscribo en un TransactionScope en curso?
Si usa un TransactionScope , puede crear una transacción "ambiental" :
using (TransactionScope scope = new TransactionScope()) { //...stuff happens, then you complete... // The Complete method commits the transaction. scope.Complete(); } ¿Para qué sirve eso? Bueno, hay algunas clases en el marco .NET que saben cómo verificar si hay una transacción ambiental en curso al verificar la static :
Esto les permite saber que hay una transacción en curso.
Por ejemplo, si tuviera alguna operación de base de datos arbitraria que de otro modo no consideraría las transacciones:
void DropStudents() { using (var cmd = connection.CreateCommand()) { cmd.CommandText = "DROP TABLE Students;"; cmd.ExecuteNonQuery(); } }Si coloca eso en medio de un TransactionScope :
using (TransactionScope scope = new TransactionScope()) { DropStudents(); // The Complete method commits the transaction. scope.Complete(); }De repente, sus operaciones de ADO.net están en una transacción; y se puede revertir.
La biblioteca SqlClient sabe verificar:
y automáticamente internamente:
Y todo es pura magia.
DbConnection recibe una notificación para llamar a .CommitDbConnection recibe una notificación para llamar a .RollbackTengo una clase que también tiene transacciones. Y en lugar de obligar a la persona que llama a llamar:
using (IContosoTransaction tx = turboEncabulator.BeginTransaction()) { try { turboEncabulator.UpendCardinalGrammeters(); } catch (Exception ex) { tx.Rollback(); throw; } tx.Commit(); }Sería bueno si pudieran llamar a:
turboEncabulator.UpendCardinalGrammeters();Y mi código simplemente verificará:
Y si hay una transacción en curso, lo haré:
Pero, ¿cómo hago eso?
¿Cómo me registro en un TransactionScope en curso para recibir estas notificaciones?
No es tan malo en realidad.
Compruebe si hay una transacción en curso al ver si System.Transactions.Transaction.Current está asignado. Si lo hay, Enlist en la transacción:
//Enlist in any current transactionScope if one is active if (System.Transactions.Transaction.Current != null) System.Transactions.Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None); Y luego debe implementar los cuatro métodos de notificación de IEnlistmentNotification :
void Prepare(PreparingEnlistment preparingEnlistment);void Commit(Enlistment enlistment);void InDoubt(Enlistment enlistment);void Rollback(Enlistment enlistment);Las implementaciones reales son notificaciones repetitivas triviales:
preparingEnlistment.Prepared();preparingEnlistment.ForceRollback();enlistment.Done();enlistment.Done();enlistment.Done(); public void Prepare(PreparingEnlistment preparingEnlistment) { //The transaction manager is asking for our vote if the transaction //can be committed //Vote "yes" by calling .Prepared: preparingenlistment.Prepared(); //Vote "no" by calling .ForceRollback: //preparingEnlistment.ForceRollback(); } public void Commit(Enlistment enlistment) { //The transaction is being committed - do whatever it is we do to commit. //Let them know we're done with the enlistment. enlistment.Done(); } public void InDoubt(Enlistment enlistment) { //Do any work necessary when indoubt notification is received. //This method is called if the transaction manager loses contact with one or more participants, //so their status is unknown. //If this occurs, you should log this fact so that you can investigate later whether any of the //transaction participants has been left in an inconsistent state. //Let them know we're done with the enlistment. enlistment.Done(); } public void Rollback(Enlistment enlistment) { //If any resource manager reported a failure to prepare in phase 1, the transaction manager invokes //the Rollback method for each resource manager and indicates to the application the failure of the commit. //Let them know we're done with the enlistment. enlistment.Done(); }