Pregunta

He estado trabajando en esto durante aproximadamente un día y medio ahora, y busqué blogs numerosos y artículos de ayuda en la web. Encontré varias preguntas sobre este error, pero no pensé que se aplicaron bastante a mi situación (o en algunos casos, desafortunadamente, no pude entenderlas lo suficientemente bien como para implementar: P). No estoy seguro de poder describir esto lo suficientemente bien para ayudar ... pero aquí va:

Tenemos una aplicación .NET para rastrear nuestros recursos. Hay una función de exportación para copiar un recurso al sistema de seguimiento de tiempo y al sistema de facturación; Esto accede a un procedimiento almacenado que se vincula con las bases de datos de tiempo y facturación.

Recientemente moví la base de datos del sistema de facturación a un nuevo servidor (servidor original: Server 2003 SP2, SQL 2005; nuevo servidor: Server 2008 R2, SQL 2008 R2). Tengo un servidor vinculado configurado que apunta a las bases de datos de 2008. Actualicé el procedimiento almacenado para señalar el servidor 2008, y luego recibí un error sobre MSDTC y RPC (http://www.safnet.com/writing/tech/archives/2007/06/server_myserver.html). Habilité 'RPC/RPC Out' en el servidor vinculado y establecí MSDTC para permitir el acceso a la red (algo como esto: http://www.sqlwebpedia.com/content/msdtc-troublesShooting).

Ahora obtengo lo anterior, cuando intento ejecutar la función de exportación: "Esta SQLTransaction se ha completado; ya no se puede usar". Lo que me parece extraño es que cuando solo ejecuto el procedimiento almacenado (de SSMS), dice que se completa con éxito.

¿Alguien ha visto esto antes? ¿Me he perdido algo en la configuración? Sigo revisando las mismas páginas, y lo único que encontré fue que no reinicié después de hacer los cambios MSDTC (mencionados aquí: http://social.msdn.microsoft.com/forums/en-us/adodotnetdataproviders/thread/7172223f-acbe-4472-8cdf-feec80fd2e64/).

Puedo publicar una parte o la totalidad del procedimiento almacenado, si ayuda ... hágamelo saber.

¿Fue útil?

Solución

Creo que este mensaje de error se debe a una "transacción zombie".

Busque posibles áreas donde el Transacton se comete dos veces (o se enrolle dos veces, o se enrolle hacia atrás y cometiera, etc.). ¿El código .NET confirma la transacción después de que el SP ya lo ha cometido? ¿El código .NET lo vuelve a poner en encontrar un error, luego intenta volver a rodarlo en una cláusula de captura (o finalmente)?

Es posible que una condición de error nunca se haya golpeado en el servidor antiguo, y por lo tanto el código de "doble reversión" defectuoso nunca fue alcanzado. Tal vez ahora tengas una situación en la que hay es Algunos errores de configuración en el nuevo servidor, y ahora el código defectuoso se está presionando mediante el manejo de excepciones.

¿Puedes depurar en el código de error? ¿Tienes un rastro de pila?

Otros consejos

Recientemente tuve esto después de refactorizar en un nuevo gerente de conexión. Una nueva rutina aceptó una transacción, por lo que podría ejecutarse como parte de un lote, el problema fue con un bloque de uso:

public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null)
{
  using (transaction.Connection)
  {
    using (transaction)
    {
      return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure);
    }
  }
}

Parece que el uso externo estaba cerrando la conexión subyacente, por lo que cualquier intento de cometer o revertir la transacción arrojó el mensaje "This SqlTransaction has completed; it is no longer usable."

Eliminé los usos agregó una prueba de cobertura y el problema desapareció.

public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null)
{
  return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure);
}

Verifique cualquier cosa que pueda cerrar la conexión mientras está dentro del contexto de una transacción.

Tengo el mismo problema. Este error ocurre porque la agrupación de la concección. Cuando existe, dos o más usuarios adquiren el sistema, la agrupación de la conexión reutiliza una conexión y la transacción también. Si el primer usuario ejecuta Commit OU Rollback, la transacción no es utilizable.

Recientemente me he encontrado con una situación similar. Para depurar en cualquier versión VS IDE, abra excepciones de la depuración (Ctrl + D, E): verifique todas las casillas de verificación con la columna "lanzada" y ejecute la aplicación en modo de depuración. Me he dado cuenta de que una de las tablas no se importó correctamente en la nueva base de datos, por lo que la excepción interna de SQL estaba matando la conexión, por lo que resulta en este error.

GIST de la historia es que, si el código de trabajo previamente devuelve este error en una nueva base de datos, este podría ser el problema de la falta de esquema de la base de datos, realizado por el consejo de depuración anterior,

Espero que ayude, Hydtechie

En mi caso, el problema era que una de las consultas incluidas en la transacción estaba planteando una excepción, y aunque la excepción se manejó "con gracia", aún logró revertir toda la transacción.

Mi pseudo-código era como:

var transaction = connection.BeginTransaction();
for(all the lines in a file)
{
     try{
         InsertLineInTable(); // INSERT statement might fail and throw an exception
     }
     catch {
         // notify the user about the error on line x and continue
     }
}

// Commit and Rollback will fail if one of the queries 
// in InsertLineInTable threw an exception
if(CheckTableForErrors())
{
    transaction.Commit();
}
else
{
    transaction.Rollback();
}

También verifique los procesos de larga duración ejecutados desde su aplicación .NET en el DB. Por ejemplo, puede llamar a un procedimiento o consulta almacenada que no tiene suficiente tiempo para terminar, lo que puede mostrarse en sus registros como:

  • El tiempo de espera de ejecución expiró. El período de tiempo de espera transcurrido antes de la finalización de la operación o el servidor no está respondiendo.

    • Esta SQLTransaction se ha completado; Ya no se puede usar.

Verifique la configuración del tiempo de espera del comando intente ejecutar un rastro (perfilador) y vea lo que está sucediendo en el lado de la DB ...

En mi caso, tengo algunos códigos después de cometer la transacción en el mismo BLOQUE DE TRAT Catch. Un error puede llevar la ejecución al bloque de captura que contiene la reversión de la transacción. Mostrará el error similar. Por ejemplo, mire la estructura de código a continuación:

SqlTransaction trans = null;

try{
 trans = Con.BeginTransaction();
// your codes

  trans.Commit();
//your codes having errors

}
catch(Exception ex)
{
     trans.Rollback(); //transaction roll back
    // error message
}

finally
{ 
    // connection close
}

Espero que ayude a alguien :)

Aquí hay una forma de detectar la transacción zombie

SqlTransaction trans = connection.BeginTransaction();

//some db calls here

if (trans.Connection != null) //Detecting zombie transaction
{
  trans.Commit();
}

Descompilar la clase SQLTransaction, verá lo siguiente

public SqlConnection Connection
{
  get
  {
    if (this.IsZombied)
      return (SqlConnection) null;
    return this._connection;
  }
}

Noto que si la conexión está cerrada, el transp se convertirá en zombie, por lo que no puede Commit. Para mi caso, es porque tengo el Commit() dentro de una finally bloque, mientras la conexión estaba en el try bloquear. Esta disposición está causando que la conexión se elimine y se recolecte la basura. La solución era poner Commit dentro de try bloquear en su lugar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top