Usando per IDbConnection / IDbTransaction sicuro da usare?

Sebbene la mia ipotesi possa sembrare soggettiva, dopo alcune ricerche, ho scoperto che non è raro trovare sviluppatori che preferiscono un fittizio Try/Catch anziché utilizzare l’ istruzione Using per l’elaborazione IDbConnection/IDbTransaction (Close / Commit / Rollback).

Ciò vale anche per alcuni degli sviluppatori più esperti e alcuni nuovi. Non farò intenzionalmente riferimento a nessuna delle domande su StackOverflow o collegamenti ai forum come esempio, quindi le persone non si offendono. Da quello che ho trovato , l’ uso di statement è sicuro da usare (nessun gioco di parole).

C’è qualcosa di sbagliato in questo? Considera il seguente codice:

 Public Sub Commit() Dim cn As IDbConnection = {CREATE_CONNECTION} Dim tran As IDbTransaction = Nothing cn.Open() Try tran = cn.BeginTransaction 'run some queries here tran.Commit() Catch ex As Exception If Not tran Is Nothing Then tran.Rollback() Throw Finally cn.Close() End Try End Function 

Supponiamo che {CREATE_CONNECTION} sia un {CREATE_CONNECTION} per un Sub che crea una connessione, a seconda del fornitore del database, scritto secondo tutte le migliori pratiche possibili e non necessita di ulteriori miglioramenti.

C’è una ragione per cui il codice di cui sopra non può essere riscritto in quanto tale:

 Using cn As IDbConnection = {CREATE_CONNECTION} cn.Open() Using tran As IDbTransaction = cn.BeginTransaction 'run some queries here tran.Commit() End Using End Using 

?

Chiaramente, la versione 2 è più intuitiva di ciò che sta facendo. Ma forse mi manca qualcosa di importante qui? Cose come implementazioni specifiche del fornitore di librerie di accesso ai dati, che non chiamano Transaction.Commit e / o Connection.Close su Dispose internamente? Questo approccio è in fase di dismissione nel prossimo futuro o non è considerato sufficientemente chiaro nelle moderne modalità di programmazione / migliori pratiche? Strumenti di sviluppo di app mono / mobile privi del supporto di debug per l’ Using parola chiave?

Sto cercando qualsiasi tipo di risposta per sostenere o negare il punto. Preferibilmente quello con le citazioni alla documentazione originale, qualcosa come Do not use Using with IDbTransaction when ... Anche i link ai blog o all’esperienza personale vanno bene.

Sono completamente con te sulla connessione; che dovrebbe essere using e non è necessario Close() esplicitamente Close() . La transazione è un po ‘più complicata; il codice mostrato è sicuramente eccessivo, ma non è del tutto definito che Dispose() debba eseguire un rollback. In realtà, questo è ciò che tende ad accadere in ogni implementazione che ho visto, ma è un po ‘ DbTransaction che anche DbTransaction (che la maggior parte dei provider usa) in realtà non lo faccia. Contrasto con TransactionScope cui è esplicitamente definito che un Dispose() senza un commit conta come un rollback. Per questo motivo , tendo ad usare (scusate il C #):

 using(var conn = GetOpenConnection()) using(var tran = conn.BeginTransaction()) { try { // TODO: do work tran.Commit(); } catch { tran.Rollback(); throw; } } 

che è da qualche parte tra i due in termini di complessità. Almeno non si scherza con null -check.

Quello che vedi è la codifica degli sviluppatori in base alla documentazione (una “buona cosa”). La class base DbTransaction (utilizzata per la maggior parte delle implementazioni delle transazioni dei fornitori di dati) afferma chiaramente nella sua documentazione :

Smaltimento dovrebbe effettuare il rollback della transazione. Tuttavia, il comportamento di Dispose è specifico del provider e non dovrebbe sostituire il richiamo del rollback.