Con EF6 tiene una nueva transacción que se puede utilizar como:
using (var context = new PostEntityContainer())
{
using (var dbcxtransaction = context.Database.BeginTransaction())
{
try
{
PostInformation NewPost = new PostInformation()
{
PostId = 101,
Content = "This is my first Post related to Entity Model",
Title = "Transaction in EF 6 beta"
};
context.Post_Details.Add(NewPost);
context.SaveChanges();
PostAdditionalInformation PostInformation = new PostAdditionalInformation()
{
PostId = (101),
PostName = "Working With Transaction in Entity Model 6 Beta Version"
};
context.PostAddtional_Details.Add(PostInformation);
context.SaveChanges();
dbcxtransaction.Commit();
}
catch
{
dbcxtransaction.Rollback();
}
}
}
¿Es realmente necesaria la reversión cuando las cosas van de lado? Tengo curiosidad porque la descripción de Commit dice: "Confirma la transacción de la tienda subyacente".
Mientras que la descripción de Rollback dice: "Retrotrae la transacción de la tienda subyacente".
Esto me da curiosidad, porque me parece que si no se llama a Commit, los comandos ejecutados anteriormente no se almacenarán (lo que me parece lógico). Pero si ese es el caso, ¿cuál sería la razón para llamar a la función Rollback? En EF5 utilicé TransactionScope que no tenía una función Rollback (solo un Completo) que me parecía lógico. Debido a razones de MS DTC, ya no puedo usar TransactionScope, pero tampoco puedo usar una captura de prueba como en el ejemplo anterior (es decir, solo necesito la confirmación).
fuente
SaveChanges
solo una vez).Respuestas:
No necesita llamar
Rollback
manualmente porque está usando lausing
declaración.DbContextTransaction.Dispose
se llamará al método al final delusing
bloque. Y revertirá automáticamente la transacción si la transacción no se confirma correctamente (no se llama o no se encuentran excepciones). A continuación se muestra el código fuente delSqlInternalTransaction.Dispose
método (DbContextTransaction.Dispose
finalmente se lo delegará cuando use el proveedor SqlServer):private void Dispose(bool disposing) { // ... if (disposing && this._innerConnection != null) { this._disposing = true; this.Rollback(); } }
Verá, verifica si
_innerConnection
no es nulo, si no, deshace la transacción (si se confirma,_innerConnection
será nulo). Veamos queCommit
hace:internal void Commit() { // Ignore many details here... this._innerConnection.ExecuteTransaction(...); if (!this.IsZombied && !this._innerConnection.IsYukonOrNewer) { // Zombie() method will set _innerConnection to null this.Zombie(); } else { this.ZombieParent(); } // Ignore many details here... } internal void Zombie() { this.ZombieParent(); SqlInternalConnection innerConnection = this._innerConnection; // Set the _innerConnection to null this._innerConnection = null; if (innerConnection != null) { innerConnection.DisconnectTransaction(this); } }
fuente
Siempre que siempre utilice SQL Server con EF, no es necesario utilizar explícitamente la captura para llamar al método Rollback. Permitir que el bloque de uso retroceda automáticamente en cualquier excepción siempre funcionará.
Sin embargo, cuando lo piensa desde el punto de vista de Entity Framework, puede ver por qué todos los ejemplos usan la llamada explícita para deshacer la transacción. Para EF, el proveedor de la base de datos es arbitrario y conectable y el proveedor puede ser reemplazado por MySQL o cualquier otra base de datos que tenga una implementación de proveedor EF. Por lo tanto, desde el punto de vista de EF, no hay garantía de que el proveedor revertirá automáticamente la transacción dispuesta, porque el EF no conoce la implementación del proveedor de la base de datos.
Por lo tanto, como una mejor práctica, la documentación de EF recomienda que se deshaga explícitamente, en caso de que algún día cambie de proveedor a una implementación que no se deshaga automáticamente al eliminar.
En mi opinión, cualquier proveedor bueno y bien escrito revertirá automáticamente la transacción en el desecho, por lo que el esfuerzo adicional para envolver todo dentro del bloque using con un try-catch-rollback es excesivo.
fuente
fuente