TransactionScope vs Transaction in LINQ to SQL

Quali sono le differenze tra il modello di transazione classico in LINQ a SQL come:

using(var context = Domain.Instance.GetContext()) { try { context.Connection.Open(); context.Transaction = context.Connection.BeginTransaction(); /*code*/ context.Transaction.Commit(); } catch { context.Transaction.Rollback(); } } 

vs l’object TransactionScope

 using (var context = Domain.Instance.GetContext()) using (var scope = new TransactionScope()) { try { /*code*/ scope.Complete(); } catch { } } 

Linq2SQL utilizzerà una transazione implicita. Se tutti gli aggiornamenti vengono eseguiti in un singolo invio, potrebbe non essere necessario gestire la transazione da soli.

Dalla documentazione (sottolineatura mia):

Quando si chiama SubmitChanges, LINQ to SQL verifica se la chiamata si trova nell’ambito di una transazione o se la proprietà Transaction (IDbTransaction) è impostata su una transazione locale avviata dall’utente. Se non trova nessuna transazione, LINQ to SQL avvia una transazione locale (IDbTransaction) e la utilizza per eseguire i comandi SQL generati. Quando tutti i comandi SQL sono stati completati correttamente, LINQ to SQL esegue il commit della transazione locale e restituisce.

Va notato che quando si utilizza TransactionScope non è necessario il costrutto try/catch si ha. Devi semplicemente chiamare Complete sull’ambito per commettere la transazione quando l’oscilloscopio viene chiuso.

Detto questo, TransactionScope è in genere una scelta migliore perché consente di annidare le chiamate ad altri metodi che potrebbero richiedere una transazione senza che sia necessario passare lo stato della transazione.

Quando si chiama BeginTransaction sull’object DbConnection , è necessario passare quell’object di transazione in giro se si desidera eseguire altre operazioni nella stessa transazione, ma con un metodo diverso.

Con TransactionScope , finché esiste l’ambito, gestirà tutto ciò che si registra con la Transaction corrente sul thread, rendendo il tuo codice più pulito e più manutenibile.

Oltre a ciò, hai il vantaggio di essere in grado di utilizzare altre risorse che possono partecipare alle transazioni, non solo la connessione al database.

Va notato che in situazioni in cui è necessario spremere il massimo dalle connessioni e dalle operazioni del database, è ansible che non si desideri utilizzare TransactionScope ; anche contro un singolo database, si esegue la possibilità che il Distributed Transaction Coordinator venga utilizzato e che la transazione venga trasformata in una transazione distribuita (anche per una singola connessione al database).

In questi casi, mentre confondete il vostro disegno, potreste considerare di passare una transazione specifica della connessione.

Oppure , se sai che utilizzerai una risorsa in modo coerente (e sullo stesso thread), potresti voler creare una class che faccia riferimento alla tua connessione / transazione.

Dovresti creare una class che sulla costruzione, crea la tua risorsa / incrementa il conteggio. Implementerebbe anche IDisposable (in cui si decrementerebbe / release / commit / abort quando il conteggio è zero) e memorizzerebbe il conteggio in una variabile a cui è applicato ThreadStaticAttribute .

Ciò consente di separare la gestione delle transazioni dal codice logico e di conservare una risorsa singolare in modo abbastanza efficiente (anziché eseguire l’escalation su una transazione distribuita).

Una grande differenza (lezione appresa nel modo più duro): TransactionScope utilizza MS DTC per la gestione delle transazioni.

Se l’applicazione deve gestire solo la transazione del database e non sono coinvolti servizi o chiamate remote, è ansible saltare i potenziali problemi relativi a MS DTC utilizzando la transazione nativa nei database (DbTransactions).

TransactionScope fornisce gestione unificata per tutti i gestori di risorse (server SQL, directory triggers, file system, …). Inoltre, si può scrivere il proprio gestore di risorse: codice che rileva l’ambito della transazione, unirsi a esso e funziona esattamente come fa il server SQL: impegna o ripristina le modifiche come gli altri partecipanti alla transazione. Credevo che TransactionScope fosse mainstream e abbia dimenticato le transazioni native di MS SQL fino al fallimento in una trappola enorme: Windows Server 2008 WEB Edition viene fornito con il servizio Distributed Transaction Coordinator limitato e lo scope Transaction funziona solo su un singolo computer. L’applicazione ASP.NET avrà esito negativo su questo sistema se IIS e SQL Server sono installati su computer diversi. Tenere presente che la maggior parte dei provider di dominio pubblico fornisce l’edizione di Windows Server WEB e il server SQL su server separati. Ciò significa che è necessario lavorare con le transazioni native utilizzando la gestione delle transazioni esplicite …

Credo che siano fondamentalmente gli stessi che la class TransactionScope si interfaccia con la connessione sottostante ADO.NET per creare ed eseguire il commit o il rollback della transazione. Che la class TransactionScope è stata appena creata per funzionare con il pulitore di persistenza ADO.NET.

Modifica: chiarendo la mia affermazione in merito all’aggiunta di casperOne, TransactionScope creerà la transazione e la connessione vedrà quindi la transazione creata da TransactionScope e la utilizzerà in quanto disponibile.