2010-05-18 24 views
7

Tengo una pregunta similar a how to check if you are in a transaction. En lugar de verificar, ¿cómo permito las transacciones anidadas?¿Cómo habilito las transacciones anidadas con ADO.NET y SQL Server?

Estoy usando la base de datos de Microsoft SQL Server con ADO.NET. He visto ejemplos usando T-SQL y ejemplos de inicio de transacciones usando comenzar y usar nombres de transacciones. Al llamar connection.BeginTransaction, llamo otra función en la misma conexión, y llama de nuevo BeginTransaction que me da la excepción:

SqlConnection does not support parallel transactions. 

Parece muchas variantes Microsoft permiten esto, pero no puedo encontrar la manera de hazlo con mi archivo .mdf.

¿Cómo puedo permitir transacciones anidadas con una base de datos de Microsoft SQL Server usando C# y ADO.NET?

Respuesta

7

SQL Server en su conjunto no admite transacciones anidadas. En T-SQL puede emitir un BEGIN TRAN dentro de un anterior BEGIN TRAN pero esto es solo por conveniencia. Es solo la transacción externa lo que cuenta. El cliente .NET para SQL Server (SqlConnection) ni siquiera le permite hacer eso y lanza esta excepción cuando lo intenta.

+0

Mi host dice que ofrecen 'Microsoft SQL 2008'. ¿Es este T-SQL? Si no, ¿de dónde viene T-SQL? Solo quiero contar la transacción externa. ¿'Microsoft SQL 2008' no permite esto? (¿Quizás para configurarlo para que no arroje una excepción?) –

+0

T-SQL es la variante de Microsoft del estándar SQL que se ejecuta en todas las versiones de SQL Server. Si desea evitar esta excepción, simplemente evite llamar a 'BeginTransaction' antes de comprometer o anular una transacción anterior; no puede ser una transacción si una transacción anterior aún está pendiente. Le recomiendo que eche un vistazo al uso de TransactionScope (http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope(VS.80).aspx) en lugar de intentar administrarlo usted mismo. –

+0

hmm, eso no es lo mismo. Este código se usó con sqlite y no estoy seguro de si es compatible con él (podría ser porque parece ser compatible con todo ado.net). Pero esto suena extraño, si T-SQL está en todas las versiones del servidor sql entonces ¿no debería tener eso y no debería ser permitido? Esa característica me hará la vida más fácil. Aunque solo hay una función que lo usa (supongo que podría destruirlo ya que solo está en init, donde solo se usa una conexión hasta que se complete). –

1
SqlConnection conn = new SqlConnection(@"Data Source=test;Initial Catalog=test;User ID=usr;Password=pass"); 
conn.Open(); 
var com = conn.CreateCommand(); 

com.CommandText = "BEGIN TRANSACTION"; 
com.ExecuteNonQuery(); 
com.CommandText = "BEGIN TRANSACTION"; 
com.ExecuteNonQuery(); 
com.CommandText = "INSERT INTO testTable (ParamName,ParamValue) values ('test','test');"; 
com.ExecuteNonQuery(); 
com.CommandText = "COMMIT TRANSACTION"; 
com.ExecuteNonQuery(); 
com.CommandText = "ROlLBACK TRANSACTION"; 
com.ExecuteNonQuery(); 

com.CommandText = "SELECT COUNT(*) FROM testTable "; 

MessageBox.Show(string.Format("Found {0} rows.", com.ExecuteScalar())); 
+0

Esta respuesta podría beneficiarse de algunos comentarios sobre lo que descubrió al ejecutarlo. – jocull

3

Es un error común que SQL Server admite transacciones anidadas. No es asi. abrir múltiples transacciones y luego realizar commit no hace absolutamente nada. puede escribir fácilmente una prueba SQL para probar esto usted mismo. La única opción aquí para emular una transacción anidada es usar Savepoints.

Debo añadir que lo único que importa cuando @@ TRAN_COUNT llega a cero es el punto en el que solo se comprometerá la transacción externa.

Cuestiones relacionadas