Publicado en .NET Framework, C# - Csharp, LinQ, Programacion, Visual Studio

Manejo de Transacciones en Entity Framework 6

Volviendo a los tutoriales de programacion, dejare un par de ejemplos de uso de transacciones en Entity Framework.

Primero, veremos una base de datos con dos tablas de ejemplo para nuestro ejemplo: Ventas y Ventas Detalle:

1) Uso de Begin Transaction

Aquí crearemos una transacción “tradicional” para grabar las dos tablas ventas y Ventas_Detalle en un solo evento.

Las tablas estan vacias al inicio de esta prueba.

A la tabla “VENTA” le coloco a mano el venta_id = “1”, por modelo a la tabla “VENTA_DETALLE” el mismo valor pero el campo PRODUCTO lo dejo en NULL para generar un error a proposito y genere el Rollback respectivo.

using (var context = new TransactionEntities())
            {
                context.Database.Log = Console.Write;

                using (DbContextTransaction transaction = context.Database.BeginTransaction())
                {
                    try
                    {
                        context.Venta.Add(new Venta()
                        {
                            dv = "9",
                            fecha_venta = DateTime.Now,
                             rut = 1,
                             venta_id = "1"
                              
                        });
                        context.SaveChanges();

                        context.Venta_Detalle.Add(new Venta_Detalle()
                        { cantidad = 10,
                          producto = null, //error para generar rollback
                          total = 100,
                          unitario = 10,
                          venta_detalle_id = "1",
                          venta_id = "1"
                        });
                        context.SaveChanges();

                        transaction.Commit();

                        MessageBox.Show("Transaction Ok!");
                    }
                    catch (DbEntityValidationException exp)
                    {
                        transaction.Rollback();

                        foreach (var eve in exp.EntityValidationErrors)
                        {
                            string msg = string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                                eve.Entry.Entity.GetType().Name, eve.Entry.State);

                            MessageBox.Show("EntityValidationErrors: " + msg);

                            foreach (var ve in eve.ValidationErrors)
                            {
                                string msg1 = string.Format("- Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage);

                                MessageBox.Show("EntityValidationErrors: " + msg1);
                            }
                        }
                        
                    }

                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        MessageBox.Show("Transaction Error occurred: " + ex.Message);
                    }
                }
            }

Al ejecutar este codigo, nos daran los siguientes mensajes de error:

Aca nos indica el error, que el PRODUCTO es requerido y no puede ser NULL

Si consultamos las tablas, estan estan vacias aun ya que no se completo la transaccion

Pero ahora ejecutamos el mismo codigo, pero modificando la lnea de insercion de Ventas_Detalle por:

context.Venta_Detalle.Add(new Venta_Detalle()
                        { cantidad = 10,
                          producto = "producto 1", 
                          total = 100,
                          unitario = 10,
                          venta_detalle_id = "1",
                          venta_id = "1"
                        });

Y el resultado seria:

Aca vemos los registros guardados correctamente

2) Uso de TransactionScope

Aca usaremos el Transaction Scope, que nos sirve cuando tenemos que modificar varias tablas de distintas bases o sistemas (Oracle, MySql, etc.)

Segun se ve en el codigo, usamos el TransactionScope (namespace System.Transactions) para crear una transaccion. El ReadUncommitted permite lecturas “sucias” (dirty read) a las tablas.

Ponemos el mismo erro del producto para que no se complete la Transaccion

using (var scope1 = new TransactionScope(TransactionScopeOption.Required,
                     new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
            {
                try
                {
                    using (var context = new TransactionEntities())
                    {

                        context.Venta.Add(new Venta()
                        {
                            dv = "9",
                            fecha_venta = DateTime.Now,
                            rut = 1,
                            venta_id = "2"

                        });

                        context.Venta_Detalle.Add(new Venta_Detalle()
                        {
                            cantidad = 10,
                            producto = null, //error para generar rollback
                            total = 100,
                            unitario = 10,
                            venta_detalle_id = "1",
                            venta_id = "2"
                        });

                        context.SaveChanges();
                    }

                    scope1.Complete();
                    scope1.Dispose();

                    MessageBox.Show("TransactionScope Ok!");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error - Se deshacen los cambios");
                }
            }

Nos da un error:

Las tablas no se ven afectadas como en el ejemplo anterior (solo se ve el producto 1). Ahora corregimos el código y pondremos:

context.Venta_Detalle.Add(new Venta_Detalle()
                        { cantidad = 10,
                          producto = "producto 2", 
                          total = 100,
                          unitario = 10,
                          venta_detalle_id = "1",
                          venta_id = "1"
                        });

Y en las tablas podemos ver la nueva insercion:

Hasta aqui queda este mini tutorial. Quedo atentos a sus comentarios.

Links:

http://panicoenlaxbox.blogspot.com/2011/03/transactionscope-ha-venido-para.html

http://www.devjoker.com/contenidos/articulos/362/TransactionScope-Simplificando-el-trabajo-con-transacciones.aspx

https://www.codeproject.com/Articles/690136/All-About-TransactionScope

TYDW.-

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s