Stavamo cercando di eseguire alcuni controlli di integrità sullo stato del nostro database per ragioni diagnostiche, quindi abbiamo completato le nostre query ORM di modifica in TransactionScope accoppiato con una seconda query che ha eseguito la diagnostica - qualcosa di simile:TransactionScope wrapping chiamate ORM, TransactionStateAborted.CreateAbortingClone exception su second call
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, _maxTimeout))
{
ORM.DeleteItem();
ORM.CheckIntegrity();
scope.Complete();
}
e 'un ORM arrotolato a mano, ed entrambe quelle chiamate finisce per fare la loro parte in un ambito di transazione annidata giù in fondo. In altre parole, quando si scava giù, DeleteItem() ha utilizzando (TransactionScope newScope = new TransactionScope (TransactionScopeOptions.Required, _maxTimeout) {...}
e CheckIntegrity() ha anche lo stesso.
Per la maggior parte funziona bene, ma ho incontrato una strana condizione: quando qualcuno inserisce alcuni dati non validi nella query, la chiamata DeleteItem() può generare un'eccezione. livello di stack sotto il wrapper Credo che sia stata lanciata anche l'eccezione prima del che arriva a nidificare TransactionScope.
Tuttavia, quando si arriva alla creazione dell'ambito nidificata nella chiamata CheckIntegrity(), viene generato un errore "Transaction was aborted" dal costruttore CreateAbortingClone. L'eccezione interna è nulla.
La maggior parte ogni altra menzione dell'interazione CreateAbortingClone ha a che fare con la promozione DTC (o il suo fallimento) e l'eccezione interna lo riflette.
Suppongo che l'eccezione di interruzione nella chiamata CheckIntegrity() sia dovuta al fatto che DeleteItem() ha generato un'eccezione, anche se è stata ingerita.
A) è un'inferenza corretta? TransactionScope è sensibile alle eccezioni generate, gestite o meno?
B) esiste un modo per rilevarlo prima di effettuare la chiamata a CheckIntegrity()? Voglio dire oltre a rifare il nostro ORM per far salire l'eccezione o aggiungere qualche altra bandiera globale?
Grazie Mark
Rovistando un po 'più nel debugger, trovo che TransactionScope.expectedCurrent .InternalTransaction.State è TransactionStateAborted dopo la chiamata DeleteItem(), puntando la mia inferenza. Il problema è che tutti questi membri sono privati ... – user1664043
Trovato doc msdn che dice "Se si verifica un'eccezione all'interno di TransactionScope, la transazione viene contrassegnata come incoerente e viene abbandonata." ma ci sono molte cose non dette tra le righe - come non sembra importare se l'eccezione è gestita da un paio di livelli di chiamata al di sotto dell'oscilloscopio e impedisce che eventuali nuovi ambiti vengano nidificati successivamente. – user1664043
Nota in un tempo di bottiglia - alla fine ho trovato System.Transactions.Transaction.Current.TransactionInformation.Status e ho calcolato che può essere usato per dire se eventuali eccezioni (gestite o non gestite) hanno rovinato la tua transazione di wrapping. Se si tratta di TransactionStatus.Aborted you're hosed. Mi è anche venuto in mente che è possibile utilizzare una transazione di wrapping a livello esterno per rilevare quando è stata generata un'eccezione. Alla tua chiamata più esterna, non devi aspettarti chiamate db consecutive in diversi livelli. Naturalmente sarebbe meglio progettare il tuo codice per non inghiottire eventi significativi. – user1664043