Ho un oggetto padre (parte di un DAL) che contiene, tra le altre cose, una raccolta (List<t>
) di oggetti figlio.TransactionScope: evitare transazioni distribuite
Quando sto salvando l'oggetto nel DB, inserisco/aggiorno il genitore, quindi eseguo il ciclo di ciascun bambino. Per la manutenibilità, ho messo tutto il codice per il bambino in un metodo privato separato.
Stavo per utilizzare le transazioni ADO standard, ma durante i miei viaggi mi sono imbattuto nell'oggetto TransactionScope, che credo mi consenta di avvolgere tutta l'interazione DB nel metodo padre (insieme all'interazione nel metodo figlio) in una transazione.
Fin qui tutto bene ...?
Quindi la prossima domanda è come creare e utilizzare le connessioni all'interno di questo TransactionScope. Ho sentito dire che l'utilizzo di più connessioni, anche se si trovano nello stesso DB, può costringere TransactionScope a pensare che si tratti di una transazione distribuita (che implica un costoso lavoro di DTC).
È il caso? O è, come sembra che stia leggendo altrove, un caso che usa la stessa stringa di connessione (che si presterà al pooling di connessioni) andrà bene?
Più in pratica, posso ...
- creare connessioni separate nel bambino genitore & (anche se con la stessa stringa di connessione)
- creare una connessione nel genitore una farla passare attraverso un parametro (mi sembra goffo)
- Fai qualcos'altro ...?
UPDATE:
Mentre sembra sarei OK usando la mia solita .NET3.5 + e SQL Server 2008+, un'altra parte di questo progetto verrà utilizzato Oracle (10g), così ho potrebbe anche praticare una tecnica che può essere utilizzata in modo coerente tra i progetti.
Quindi passerò semplicemente la connessione ai metodi figlio.
Opzione 1 codice di esempio:
using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(connString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.Connection.Open();
cmd.CommandType = CommandType.StoredProcedure;
try
{
//create & add parameters to command
//save parent object to DB
cmd.ExecuteNonQuery();
if ((int)cmd.Parameters["@Result"].Value != 0)
{
//not ok
//rollback transaction
ts.Dispose();
return false;
}
else //enquiry saved OK
{
if (update)
{
enquiryID = (int)cmd.Parameters["@EnquiryID"].Value;
}
//Save Vehicles (child objects)
if (SaveVehiclesToEPE())
{
ts.Complete();
return true;
}
else
{
ts.Dispose();
return false;
}
}
}
catch (Exception ex)
{
//log error
ts.Dispose();
throw;
}
}
}
}
Vedere [TransactionScope passa automaticamente a MSDTC su alcune macchine?] (Http://stackoverflow.com/questions/1690892/transactionscope-automatically-escalating-to-msdtc-on-some-machines/1693795#1693795). Ci sono molte buone risposte, ma quella che ho collegato è la più sintetica (e pertinente alla tua domanda). Il risultato è che, se utilizzi .NET 2.0 e SQL Server 2005, aumenterai anche utilizzando due connessioni con la stessa stringa di connessione. Questo non è un problema con .NET 3.5 e SQL Server 2008. –
I * am * utilizza .NET 3.5/4 e SQL 2008 in generale, ma occasionalmente potrei usare SQL2005/2000, quindi vale la pena ricordare comunque. Grazie a – CJM
qualcuno può darmi qualche informazione su cosa è una transazione distribuita. spiegare con l'esempio. – Thomas