2011-05-05 9 views
7

Estoy tratando de usar un ámbito de transacción dentro de un ciclo. Todo el ciclo se lleva a cabo utilizando una única conexión a la base de datos. Estoy usando el marco de entidad 4 para el acceso a la base de datos. Durante la segunda iteración del ciclo, cuando se ejecuta la consulta LINQ to Entites, se lanza una excepción que indica que el MSDTC en el servidor no está disponible.TransactionScope siempre intenta promocionar a MSDTC

He leído que la apertura explícita de la conexión y luego alistar la transacción se supone que resuelve este problema, pero no es así. A continuación se muestra un código de muestra que refleja la operación básica que está teniendo lugar.

¿Alguna idea sobre cómo prevenir una escalada a MSDTC?

Using context = New MyEntities() 
    Dim connection = context.Connection 

    connection.Open() 

    For index = 0 to (Me.files.Count - 1) 
     Dim query = From d In context.Documents 
        Where (d.DocumentID = documentID) 
        Select d.Status 

     Dim status = query.FirstOrDefault() 

     Using trans = New TransactionScope() 
      connection.EnlistTransaction(Transaction.Current) 

      Dim result = context.UpdateStatus(True) 

      If (result = 1) Then 
       WriteToFile() 
       trans.Complete() 
      End If 
     End Using 
    Next 
End Using 

Editar: En lugar de TransactionScope, si uso connection.BeginTransaction(), transaction.Commit(), y transaction.Rollback(), que funciona bien. Sin embargo, aún me gustaría encontrar una forma de hacer que TransactionScope funcione.

+0

¿Le sirve este foro? http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/c3fd7555-7fff-44b8-8e1e-030073c20597/ Parece que la recomendación es iniciar la transacción, luego abrir la conexión, luego ejecutar tus consultas – mkedobbs

+0

La idea era abrir la conexión, luego ejecutar todas las consultas utilizando una conexión, por razones de rendimiento. – NYSystemsAnalyst

+0

No hay razones de rendimiento para esto si usa la agrupación de conexiones. –

Respuesta

1

TransactionScope originalmente tenía un problema en el que promovía una transacción a una transacción distribuida cuando se encontraba con otra conexión, incluso si todas las conexiones estaban en la misma base de datos. Este era un problema conocido en el marco.

Creo que abordaron esto en .NET 4, ¿qué versión estás usando?

Una solución ha sido proporcionada en esta respuesta:

Why is TransactionScope using a distributed transaction when I am only using LinqToSql and Ado.Net

Básicamente lo mismo que el comentario a la pregunta que sugiere sólo para usar en realidad una conexión física de la piscina - tan sólo una conexión se alistaron .

Revisando su pregunta nuevamente Puedo ver que lo anterior probablemente no sea diferente, ya que solo usa una conexión de todas formas. Tal vez intente cerrar y volver a abrir la conexión en cada iteración explícitamente, y use los beneficios de la agrupación de conexiones.

O más idealmente, deje de utilizar TransactionScope como IDbTransaction tiene suficiente alcance aquí para cubrir su código.

+0

Una vez que usa más de una conexión, la transacción debe promocionarse a una distribuida; no hay diferencia si se conectan a la misma base de datos o no. La transacción local se maneja solo en una sola conexión cuando no hay otro recurso transaccional involucrado. –

+0

La respuesta a esta pregunta del foro sugiere que es una limitación y se tratará en: http://social.msdn.microsoft.com/forums/en-US/adodotnetdataproviders/thread/3ce488eb-55a8-4535-adc7-c5b29a1523b5/ –

+0

Sin embargo, no son exactamente la misma situación que el OP. La situación que parece que estoy comparando es cuando un alcance de transacción tiene múltiples conexiones, mientras que el OP parece tener una conexión y múltiples ámbitos de transacción ... no visto antes. –

1

¿Ha marcado la descripción para EnlistTransaction en MSDN? Dice:

Nuevo en ADO.NET 2.0 es el soporte para utilizando el método EnlistTransaction a de alta en una transacción distribuida. Debido a que alista una conexión en un caso Transacción, EnlistTransaction se aprovecha de funcionalidad disponible en el espacio de nombres System.Transactions para gestión de transacciones distribuidas. Una vez que una conexión está explícitamente alistado en una transacción, no puede ser no enlistado o alistado en otra transacción hasta que finalice la primera transacción .

Solo menciona transacciones distribuidas. Puede intentar usar connection.BeginTransaction en su lugar. Devolverá la instancia de EntityTransaction y llamará al Commit para completar la transacción.

Cuestiones relacionadas