.net - practices - entity framework transaction commit rollback c#
System.Data.EntityException: el proveedor subyacente falló en Commit (2)
Al usar Entity Framework, recibí varias de las siguientes excepciones anoche en una de mis aplicaciones:
System.Data.EntityException: The underlying provider failed on Commit. --->
System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.ReadBuffer()
at System.Data.SqlClient.TdsParserStateObject.ReadByte()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler,SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalTransaction.Commit()
at System.Data.SqlClient.SqlTransaction.Commit()
at System.Data.EntityClient.EntityTransaction.Commit()
--- End of inner exception stack trace ---
at System.Data.EntityClient.EntityTransaction.Commit()
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
Lo interesante de este error es que los datos se escribieron en realidad en la base de datos. Encontré una publicación relacionada en un sitio de MS que parecía indicar que se trataba de un error relacionado con la red.
Algunas preguntas sobre las que podría usar la asistencia son:
- ¿Qué opciones tengo para solucionar este error?
- ¿Es más que probable que esté relacionado con la red o podría el DB ser sospechoso?
- ¿Cómo puedo saber del código si la transacción realmente se completó?
- ¿Debo consultar a la base de datos sobre este error para verificar si fue exitoso o simplemente reintentar la transacción?
- Si vuelvo a intentar la transacción, ¿cómo se puede lograr esto automáticamente con Entity Framework o simplemente lo hago / reintento?
- ¿Qué otros artículos debo estar mirando?
Gracias por adelantado.
ACTUALIZAR
Al utilizar Ignite para SQL , pudimos determinar que un proceso SQL secundario de otro grupo monopolizaba la CPU e impedía que nuestra aplicación funcionara correctamente. En resumen, estamos avanzando con la adición de un servidor secundario para evitar más conflictos entre los dos equipos.
Lo que sigue siendo interesante acerca de la excepción es que la transacción realmente tuvo éxito en lugar de fracasar.
+1 para Luke, la explicación es buena. La redacción del error es desafortunada.
System.Data.EntityException: **The underlying provider failed on Commit.** --->
System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior
debe ser leído
System.Data.EntityException: **The underlying provider failed to respond to Commit**
System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior
Las causas probables son problemas de la red o del servidor. Por ejemplo, 100 CPU, u otro retraso del servidor, siguen siendo correctos. PERO NO SABE si se ha comprometido o no, si este es un caso de tiempo de espera. Si se recibió una respuesta con error, el DB debería haberse retrotraído. Por supuesto, si eso no sucedió, entonces la base de datos se ha estrellado y ha resultado en una posible corrupción. Raro espero.
He visto en una tabla de más de mil millones de dólares ... Durante la asignación de espacio en crecimiento, a medida que se necesita expandir el índice y el área de datos, tome más de 30 segundos. PERO la COMPROMISO sucedió. El cliente había agotado el tiempo. Las reorganizaciones en línea también pueden causar retrasos (bueno, al menos he visto eso en DB2)
Mi apuesta es que la respuesta exitosa del comando de confirmación de transacción no se envió (o no se envió lo suficientemente rápido) causando una excepción en su código. Un caso un poco loco de borde. Las excepciones de este tipo no significan necesariamente que la ejecución real del comando haya fallado simplemente que haya una falla.
De la misma manera, si hubiera un problema al enviar la respuesta desde una llamada de servicio web, esto no necesariamente implicaría que no se aplicaran los efectos secundarios de esa llamada.