Come menzionato da altri, TransactionScope
è la strada da percorrere.
Se si utilizza SQL Server 2008 e .NET 3.5, modificherei la progettazione affinché l'oggetto business controlli la transazione e lasci l'apertura e la chiusura della connessione al livello dati.
Con il pool di connessioni attivato, non si incorre in alcun modo nel sovraccarico dell'apertura di una connessione fisica al database e le connessioni saranno aperte solo quando si esegue il lavoro effettivo. Poiché (presumo) hai SQL Server 2008 with .NET 3.5 your transaction will not escalate to a distributed transaction (a meno che non apri più connessioni contemporaneamente) in modo da ottenere il meglio da entrambi i mondi.
allora si potrebbe scrivere il vostro oggetto business come questo:
using (TransactionScope transactionScope = new TransactionScope())
{
DataObject dataObject = new DataObject();
dataObject.UpdateQuantity(...);
ShippingManager shippingManager = new ShippingManager();
shippingManager.ShipOrder(...);
transactionScope.Complete()
}
Questo evita di dover passare le stringhe di connessione in giro a tutti gli oggetti di business e rende coordinare le transazioni facile.
Aggiornamento
La bellezza di System.Transactions è che tutte le transazioni sono gestite per voi, indipendentemente dalla connessione che si sta utilizzando. Basta dichiarare TransactionScope e tutti gli accessi al database all'interno di quel TransactionScope si verificheranno con una singola transazione (a meno che non si richieda diversamente con le diverse impostazioni di TransactionScope).
In passato (SQL Server 2005 .NET 2.0), se si apriva e si chiudeva una connessione e quindi si apriva e si chiudeva un'altra connessione (anche con la stessa stringa di connessione), la transazione veniva promossa da una transazione leggera a una distribuita Transazione. Ciò non era auspicabile in quanto le prestazioni risentono (la comunicazione con MSDTC è fuori processo e il protocollo di commit a due fasi) e MSDTC può essere difficile da configurare in molti ambienti di produzione (firewall e sicurezza).
Con SQL Server 2008 e .NET 3.5 hanno aggiunto la possibilità di evitare questa promozione quando si aprono e si chiudono più connessioni con la stessa stringa di connessione all'interno di una singola transazione. Per una spiegazione davvero buona di ciò che hanno visto Extending Lightweight Transactions in SqlClient.
Aggiornamento 2
Rapporti con Oracle 10g funzioneranno correttamente con TransactionScope. E sembra ODP.NET supports Lightweight Transactions (che è bello). Sfortunatamente, penso che la promozione di una transazione distribuita avverrà con la chiusura e l'apertura delle connessioni.
Se si desidera evitare una transazione distribuita, è possibile passare la connessione a ogni chiamata di metodo/oggetto business. Se non si desidera passare una connessione, è possibile utilizzare uno ConnectionScope class che mantiene aperta la connessione sul thread. Un'alternativa sarebbe quella di utilizzare il blocco di applicazioni di accesso ai dati di Enterprise Library 3.0 (e versioni successive). Data Access Block can detect that a transaction is in progress and use the same connection per evitare una transazione distribuita.
Anche se 'TransactionScope' * è * la classe da utilizzare qui, con la progettazione corrente dell'OP provocherà una transazione distribuita o eventualmente un'eccezione se MSDTC è disabilitato o bloccato. È * probabilmente * non il risultato desiderato. – Aaronaught
@Aaronaught, con SQL Server 2008 e .NET 3.5 la transazione non verrà promossa su una transazione distribuita (per la progettazione corrente). –
@Tuzo: true, con SQL Server 2008 è possibile ingannare il problema di connessione multipla ** SE ** tutte le connessioni sono sullo stesso database ** e ** è sempre aperta solo una allo stesso tempo. È ancora una pratica piuttosto discutibile, specialmente quando il design alternativo è più facile da costruire/mantenere comunque. – Aaronaught