Tengo un objeto principal (parte de un DAL) que contiene, entre otras cosas, una colección (List<t>
) de objetos secundarios.TransactionScope: evitar transacciones distribuidas
Cuando guardo el objeto en la base de datos, ingreso/actualizo el elemento primario y luego recorro cada elemento secundario. Para la mantenibilidad, he puesto todo el código para el niño en un método privado separado.
Iba a utilizar transacciones ADO estándar, pero en mis viajes tropecé con el objeto TransactionScope, que creo que me permitirá ajustar todas las interacciones DB en el método padre (junto con todas las interacciones en el método secundario) en una transacción
Hasta ahora todo bien ..?
Así que la siguiente pregunta es cómo crear y usar conexiones dentro de este TransactionScope. He oído que el uso de conexiones múltiples, incluso si están en la misma base de datos, puede obligar a TransactionScope a pensar que se trata de una transacción distribuida (que implica un costoso trabajo de DTC).
¿Es el caso? ¿O es que, como parece estar leyendo en otro lado, un caso que usar la misma cadena de conexión (que se prestará a la agrupación de conexiones) estará bien?
Más prácticamente hablando, puedo ...
- crear conexiones separadas en el niño los padres & (aunque con la misma cadena de conexión)
- crear un enlace en la matriz a través de un pase de como parámetro (me parece torpe)
- ¿Hace algo más ...?
ACTUALIZACIÓN:
Aunque parece que iba a estar bien usando mi .NET3.5 habitual + y SQL Server 2008+, otra parte de este proyecto va a utilizar Oracle (10g) por lo que también podría practicar una técnica que pueda usarse de manera consistente en todos los proyectos.
Así que simplemente pasaré la conexión a través de los métodos secundarios. 1 Código
opción de la muestra:
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;
}
}
}
}
Ver [TransactionScope escalando automáticamente a MSDTC en algunas máquinas?] (Http://stackoverflow.com/questions/1690892/transactionscope-automatically-escalating-to-msdtc-on-some-machines/1693795#1693795). Hay varias buenas respuestas, pero la que he vinculado es la más sucinta (y relevante para su pregunta). El resultado es que, si está utilizando .NET 2.0 y SQL Server 2005, escalará aún utilizando dos conexiones con la misma cadena de conexión. Esto no es un problema con .NET 3.5 y SQL Server 2008. –
I * estoy * usando .NET 3.5/4 y SQL 2008 en general, pero de vez en cuando podría usar SQL2005/2000, así que vale la pena recordarlo de todos modos. Gracias – CJM
¿alguien puede darme algún conocimiento sobre lo que se distribuye la transacción. explicar con el ejemplo. – Thomas