Control de errores de confirmación de transacciones

Nota:

Solo EF6.1 y versiones posteriores: las características, las API, etc., que se describen en esta página se han incluido a partir de Entity Framework 6.1. Si usa una versión anterior, no se aplica parte o la totalidad de la información.

Como parte de la versión 6.1, se introduce una nueva característica de resistencia de conexión para EF: la capacidad de detectar y recuperarse automáticamente cuando los errores transitorios de conexión afectan a la confirmación de las confirmaciones de transacciones. Los detalles completos del escenario se describen mejor en la entrada de blog Conectividad de SQL Database y el problema de la idempotencia. En resumen, el escenario es que, cuando se produce una excepción durante una confirmación de transacción, hay dos causas posibles:

  1. Se ha producido un error de confirmación de transacción en el servidor
  2. La confirmación de transacción se ha realizado correctamente en el servidor, pero un problema de conectividad ha impedido que la notificación del éxito llegara al cliente

Cuando se produce la primera situación, la aplicación o el usuario puede reintentar la operación, pero cuando se produce la segunda, se deben evitar reintentos y la aplicación podría recuperarse automáticamente. El desafío es que sin la capacidad de detectar el motivo real por el que se ha notificado una excepción durante la confirmación, la aplicación no puede elegir la acción correcta. La nueva característica de EF 6.1 permite que EF vuelva a comprobar con la base de datos si la transacción se ha realizado correctamente y adopta la acción correcta de forma transparente.

Uso de la característica

Para habilitar la característica, debe incluir una llamada a SetTransactionHandler en el constructor de la instancia de DbConfiguration. Si no está familiarizado con DbConfiguration, veaConfiguración basada en código. Esta característica se puede usar en combinación con los reintentos automáticos introducidos en EF6, lo que sirve de ayuda cuando la que la transacción realmente no se ha podido confirmar en el servidor debido a un error transitorio:

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.SqlServer;

public class MyConfiguration : DbConfiguration  
{
  public MyConfiguration()  
  {  
    SetTransactionHandler(SqlProviderServices.ProviderInvariantName, () => new CommitFailureHandler());  
    SetExecutionStrategy(SqlProviderServices.ProviderInvariantName, () => new SqlAzureExecutionStrategy());  
  }  
}

Procedimiento de seguimiento de las transacciones

Cuando se habilita la característica, EF agregará automáticamente una nueva tabla a la base de datos denominada __Transactions. Se inserta una nueva fila en esta tabla cada vez que EF crea una transacción y en esa fila se comprueba si existe un error de transacción durante la confirmación.

Aunque EF realizará el mejor esfuerzo para eliminar las filas de la tabla cuando ya no sean necesarias, la tabla puede crecer si la aplicación se cierra de forma prematura y, por ese motivo, es posible que en algunos casos tenga que purgar la tabla manualmente.

Procedimiento para controlar errores de confirmación con versiones anteriores

Antes de EF 6.1 no había ningún mecanismo para controlar los errores de confirmación en el producto EF. Hay varias maneras de tratar esta situación que se pueden aplicar a versiones anteriores de EF6:

  • Opción 1: No hacer nada

    La probabilidad de un error de conexión durante la confirmación de la transacción es baja, por lo que puede ser aceptable que solo se produzca un error en la aplicación si realmente se da esta condición.

  • Opción 2: Uso de la base de datos para restablecer el estado

    1. Descartar la instancia actual de DbContext
    2. Cree una instancia de DbContext y restaure el estado de la aplicación desde la base de datos
    3. Informe al usuario de que es posible que la última operación no se haya completado correctamente
  • Opción 3: Seguimiento manual de la transacción

    1. Agregue una tabla sin seguimiento a la base de datos utilizada para realizar el seguimiento del estado de las transacciones.
    2. Inserte una fila en la tabla al principio de cada transacción.
    3. Si se produce un error en la conexión durante la confirmación, compruebe la presencia de la fila correspondiente en la base de datos.
      • Si la fila está presente, continúe con normalidad, ya que la transacción se ha confirmado correctamente
      • Si la fila no está presente, use una estrategia de ejecución para reintentar la operación actual.
    4. Si la confirmación se realiza correctamente, elimine la fila correspondiente para evitar el crecimiento de la tabla.

Esta entrada de blog contiene código de ejemplo para realizarlo en Azure SQL.