He estado investigando las transacciones y parece que cuiden de sí mismos en EF, siempre y cuando paso false
a SaveChanges()
y luego llamar AcceptAllChanges()
si no hay errores:
SaveChanges(false);
// ...
AcceptAllChanges();
¿Qué pasa si algo sale mal? ¿No tengo que retroceder o, tan pronto como mi método se sale del alcance, se finaliza la transacción?
¿Qué sucede con las columnas de sangría que se asignaron a la mitad de la transacción? Supongo que si alguien más agregó un registro después del mío antes de que el mío saliera mal, entonces esto significa que habrá un valor de identidad faltante.
¿Hay alguna razón para usar la TransactionScope
clase estándar en mi código?
c#
entity-framework
transactions
Mark Smith
fuente
fuente
SaveChanges(fase); ... AcceptAllChanges();
era un patrón en primer lugar. Observe cómo la respuesta aceptada a la pregunta anterior está escrita por el autor de un blog , y ese blog se menciona en la otra pregunta. Todo se une.Respuestas:
Con Entity Framework, la mayoría de las veces
SaveChanges()
es suficiente. Esto crea una transacción, o se alista en cualquier transacción ambiental, y realiza todo el trabajo necesario en esa transacción.A veces, aunque el
SaveChanges(false) + AcceptAllChanges()
emparejamiento es útil.El lugar más útil para esto es en situaciones en las que desea realizar una transacción distribuida en dos contextos diferentes.
Es decir, algo como esto (malo):
Si
context1.SaveChanges()
tiene éxito perocontext2.SaveChanges()
falla, se anula toda la transacción distribuida. Pero desafortunadamente, Entity Framework ya ha descartado los cambioscontext1
, por lo que no puede reproducir o registrar efectivamente la falla.Pero si cambia su código para que se vea así:
Si bien la llamada a
SaveChanges(false)
envía los comandos necesarios a la base de datos, el contexto en sí no cambia, por lo que puede hacerlo nuevamente si es necesario, o puede interrogarObjectStateManager
si lo desea.Esto significa que si la transacción realmente arroja una excepción que puede compensar, ya sea reintentando o registrando el estado de cada contexto en
ObjectStateManager
alguna parte.Vea mi publicación de blog para más.
fuente
SaveChanges(false)
realiza la actualización real de la base de datos, mientrasAcceptAllChanges()
le dice a EF: "Está bien, puedes olvidar qué cosas hay que guardar, porque se han guardado correctamente". SiSaveChanges(false)
falla,AcceptAllChanges()
nunca se llamará y EF seguirá considerando que su objeto tiene propiedades que se modificaron y deben guardarse de nuevo en la base de datos.Si está utilizando EF6 (Entity Framework 6+), esto ha cambiado para las llamadas de la base de datos a SQL.
Ver: http://msdn.microsoft.com/en-us/data/dn456843.aspx
use context.Database.BeginTransaction.
De MSDN:
fuente
throw;
Agregué el fragmento de MSDN e indiqué claramente que no es el original del artículo de MSDN.Rollback()
se llama en caso de que esté hablando con MySql o algo que no tenga ese comportamiento automático.Debido a que alguna base de datos puede lanzar una excepción en dbContextTransaction.Commit (), mejor esto:
fuente
false
encontext.SaveChanges();
, y, además, llamacontext.AcceptAllChanges();
.