Вы находитесь на странице: 1из 6

Transacciones

Utilizando la base de datos del Northwind, vamos a trabajar con 3 tablas, que son Order,[orders details] y products. El proceso es el siguiente vamos a crear una orden, luego capturamos el id de la orden generada, y la anexamos en los registros que vamos a crear en su tabla detalle de la orden, pero antes verificaremos que exista stock en los 3 productos de la orden. Nota para este ejemplo trabajaremoc con los Productos 1,2 y3 en forma definitiva. Realizar Sentencia en el SQL Server Con las tablas Orders, OrderId y Products Bueno empezamos haciendo el siguiente formulario:

Si te nos damos cuenta el cdigo del cliente lo hemos puesto en forma definitiva. Declaremos los siguientes Namespace Imports System.Data Imports System.Data.SqlClient Ahora declaremos las siguientes variables globales 'Declaracion de variables Globales Dim cn As New SqlConnection("server=.;Database=Northwind;integrated security=true;") Dim com As SqlCommand Dim Trans As SqlTransaction Ahora realizaremos la programacin de la transaccin en el botn Grabar Pedido Try 'Abrir la conexion cn.Open() 'Iniciar la Transaccion Trans = cn.BeginTransaction 'Instancia el Objeto SqlCommand com = New SqlCommand 'Asignar la conexion al objeto sqlcommand com.Connection = cn 'Asignar la Transaccion al comando com.Transaction = Trans 'Agregar registro a la tabla order com.CommandText = "Insert Into orders(CustomerId,OrderDate,Requireddate) " & _ " Values('ALFKI',getdate(),dateadd(d,14,Getdate()))" 'Ejecutamos el comando com.ExecuteNonQuery() 'Recuperar el ID del pedido agregado a la sentencia Anterior com.CommandText = "Select @@identity From Orders" Dim PedidoNro As String = com.ExecuteScalar().ToString() 'Insertar registros a la tabla OrderDetails para los prod 1,2 y3 'producto 1 com.CommandText = "Insert Into [order details](OrderId,ProductId,UnitPrice,Quantity)" & _ " values (" & PedidoNro & ",1,18," & CInt(txtc1.Text) & ")" com.ExecuteNonQuery() 'producto 2 com.CommandText = "Insert Into [order details](OrderId,ProductId,UnitPrice,Quantity)" & _ " values (" & PedidoNro & ",2,19," & CInt(txtc2.Text) & ")" com.ExecuteNonQuery() 'producto 3 com.CommandText = "Insert Into [order details](OrderId,ProductId,UnitPrice,Quantity)" & _

ADO.Net 3.5

Pgina 1

" values (" & PedidoNro & ",3,21," & CInt(txtc3.Text) & ")" com.ExecuteNonQuery() 'Averiguar el stock de cada producto 'Producto 1 com.CommandText = "Select UnitsInStock from Products where ProductId=1" Dim stock As Integer = com.ExecuteScalar If stock < CInt(txtc1.Text) Then Trans.Rollback() : MsgBox("La cantd Disponible excede al stock del producto 1") Exit Sub End If 'Producto 2 com.CommandText = "Select UnitsInStock from Products where ProductId=2" stock = com.ExecuteScalar If stock < CInt(txtc2.Text) Then Trans.Rollback() : MsgBox("La cantd Disponible excede al stock del producto 2") Exit Sub End If 'Producto 3 com.CommandText = "Select UnitsInStock from Products where ProductId=3" stock = com.ExecuteScalar If stock < CInt(txtc3.Text) Then Trans.Rollback() : MsgBox("La cantd Disponible excede al stock del producto 3") Exit Sub End If 'Grabacion de la Transaccion Trans.Commit() 'Mostrar mensaje de Exito MsgBox("El pedido generado ha sido " & PedidoNro) Catch ex As Exception MsgBox(ex.Message) Finally cn.Close() End Try End Sub

ADO.Net 3.5

Pgina 2

Ejemplo 2 - Transacciones Ahora vamos a crear una base de datos llamada Ejemplo y una tabla de nombre Persona que tiene los siguientes campos Create DataBase Ejemplo Go Use ejemplo Go Create table Persona ( Codigo varchar(10), Nombres varchar(50), Sueldo int, Estado varchar(1) ) Vamos a desarrollar un formulario el cual va a tener 2 botones, uno de ellos trabajara con transacciones al momento de insertar y el otro trabajara sin transacciones , el formulario quedara de la siguiente manera:

En un formulario que posee un botn escribimos lo siguiente en el evento clic del botn, Importemos los namespace Imports System.Data. Imports System.Data.SqlClient: Ahora dentro del Botn btnNoTransacciones, realicemos la siguiente codificacin: Private Sub btnNoTransacciones_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNoTransacciones.Click Dim Cn As New SqlConnection("Data Source=.;Initial Catalog=EJEMPLO;Integrated security=true;") 'Abrimos la Conexion Cn.Open() Try Dim cmd As New SqlCommand("INSERT INTO PERSONA (codigo, nombres, sueldo, estado) Values('JG1','JOSE',200,'A')", Cn) cmd.ExecuteNonQuery() 'Ejecutando la sentencia SQL cmd = New SqlCommand("INSERT INTO PERSONA (codigo, nombres, sueldo, estado) Values('JG2','LUIS',180,'B')", Cn) cmd.ExecuteNonQuery() 'Ejecutando la sentencia SQL cmd = New SqlCommand("INSERT INTO PERSONA (codigo, nombres, sueldo, estado) Values('JG3','PEDRO',400,'A')", Cn) cmd.ExecuteNonQuery() 'Ejecutando la sentencia SQL Catch ex As Exception MsgBox(ex.Message) End Try 'Cerramos la conexion Cn.Close() MsgBox("Datos Ingresados Correctamente") End Sub

ADO.Net 3.5

Pgina 3

Como vemos aadiremos en la tabla Persona 3 registro, pero si quisiramos convertirle a transaccin para que se ejecuten todos o ninguno si encuentra un error deberamos hacer lo siguiente. Fjese en los datos para el campo cdigo pues ahora son tr1, tr2 y tr3. Private Sub btnSiTransaaccion_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSiTransaaccion.Click Dim Cn As New SqlConnection("Data Source=.;Initial Catalog=EJEMPLO;Integrated Security=true;") Cn.Open() 'Declarando la variable Transaccion Dim myTrans As SqlTransaction Dim Cmd As SqlCommand 'Iniciando la Transaccion myTrans = Cn.BeginTransaction() Try Cmd = New SqlCommand("INSERT INTO PERSONA (codigo, nombres, sueldo, estado) Values('tr1','JOSE',200,'A')", Cn) Cmd.Transaction = myTrans Cmd.ExecuteNonQuery() Cmd = New SqlCommand("INSERT INTO PERSONA (codigo, nombres, sueldo, estado) Values('tr2','LUIS',180,'B')", Cn) Cmd.Transaction = myTrans Cmd.ExecuteNonQuery() Cmd = New SqlCommand("INSERT INTO PERSONA (codigo, nombres, sueldo, estado) Values('tr3','PEDRO',400,'A')", Cn) Cmd.Transaction = myTrans Cmd.ExecuteNonQuery() 'Grabando la Transaccion myTrans.Commit() MsgBox("Datos Ingresados Correctamente") Catch ex As Exception 'En caso de que exista un error al momento de Insertar la transaccion no se efectua myTrans.Rollback() MsgBox(ex.Message) End Try Cn.Close() End Sub Ahora al ejecutaremos el botn btnSiTransaaccion, el insertar los nuevos 3 registros, pero lo har usando transacciones para lo cual iniciamos la transaccin con myTrans = Conn.BeginTransaction() y finalizamos con myTrans.Commit() y en caso de algn error ejecutamos myTrans.Rollback() para cancelar todo lo realizado en la transaccin. Para comprobar que la transaccin se cancela al encontrar un error cambiamos los valores del campo cdigo por tr1 por cs1 y tr2 por cs2, dejando tr3 en el tercer registro pues as dar un error de clave duplicada porque ya existe un registro con esta clave previamente grabada. Al ejecutar nos saldr un mensaje que indica que existi una violacin de primary key. Si verificamos los datos, no habr ningn registro aadido pues como est en una transaccin o se agregan todos o no se agrega ninguno.

ADO.Net 3.5

Pgina 4

Ahora con DataSets En un formulario tenemos 2 botones Grabar y LeerDatos adems de un DataGrid asi:

Ahora vamos a crear una clase llamada persona que ejecute las dos acciones de los botones, aqu est el cdigo: Imports System.Data.SqlClient Public Class Persona Public Function Recuperar() As DataSet 'definimos la coneccion Dim Cn As New SqlConnection("Data Source=.;Initial Catalog=EJEMPLO;Integrated Security=true;") 'creamos el data adapter con la instruccion select a recuperar Dim adapter As New SqlDataAdapter("Select * from PERSONA", Cn ) 'abrimos la coneccion Cn.Open() 'creamos el dataset donde recuperaremos los datos de la base de datos Dim ds As New DataSet 'recuperamos los datos a travez del adapter adapter.Fill(ds, "PERSONA") 'retornamos los datos Return ds End Function Public Sub Grabar( ByVal ds As DataSet) 'definimos la coneccion Dim Cn as New SqlConnection("Data Source=.;Initial Catalog=EJEMPLO; Integrated Security=true;") 'abrimos la coneccion Cn.Open() 'creamos el data adapter con la instruccion select a recuperar Dim adapter As New SqlDataAdapter("Select * from PERSONA", Cn ) 'Creamos e inicimos la transaccion Dim Tran As SqlTransaction = Conn.BeginTransaction 'asignamos la transaccion al comando Select del adapter adapter.SelectCommand.Transaction = Tran 'construimos los demas comandos del adapter (DELETE, INSERT, UPDATE) Dim X As New SqlCommandBuilder(adapter) Try 'Actualizamos el DataSet adapter.Update(ds, "PERSONA") 'Confirmamos la transaccion Tran.Commit() MsgBox("Datos grabados con xito") Catch Ex As SqlException Dim men As String If ex.Number = 8152 Then men = "Existen datos demasiados extensos, corrija el problema y vuelva a intentar" ElseIf ex.Number = 2627 Then

ADO.Net 3.5

Pgina 5

If ex.Message.IndexOf("PRIMARY") <> -1 Then men = "Error por intentar grabar valores duplicados en campos clave, corrija el problema y vuelva a intentar" ElseIf ex.Message.IndexOf("UNIQUE") <> -1 Then men = "Error por intentar grabar valores duplicados en campos de valores nicos, corrija el problema y vuelva a intentar" Else men = "Error general en la base de datos" End If ElseIf ex.Number = 515 Then men = "Algunos datos no han sido ingresados y son necesario para completar la operacin, corrija el problema y vuelva a intentar" Else men = "Error general en la base de datos" End If 'cancelamos la transaccion Tran.Rollback() 'Indicamos el mensaje Throw New Exception(men) Catch Ex As DBConcurrencyException 'cancelamos la transaccion Tran.Rollback() 'Indicamos el mensaje Throw New Exception("Lo siento, los datos fueron actualizados por otro usuario") Catch Ex As Exception 'Indicamos el mensaje Throw New Exception("Error: " & EX.Message) End Try End Sub Luego en el formulario creado con los botones y el grid escribimos el siguiente cdigo Botn Leer Dim dt As New Persona Grid.DataSource = dt.Recuperar Botn Grabar Dim dt As New Persona Try dt.Grabar(Grid.DataSource) Grid.DataSource = dt.Recuperar Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Critical) End Try Evento Load_Form (Carga del formulario) Dim dt As New Persona Grid.DataSource = dt.Recuperar De esta forma podemos grabar y leer los datos del grid en forma transaccional, es decir que si por algn motivo existiese un error se cancelarn todas las actualizaciones. Adems esto nos es bien recomendable cuando existe concurrencia de varios usuarios sobre el mismo grupo de registros pues graba solo los registros actualizados del primer usuario que ejecuta el grabar y para los dems usuarios no graba ningn registro, que si no se lo hace en forma transaccional grabara una parte de los registros y otros no. Para esto hay que tomar en cuenta que el manejo de transacciones debe hacerse en capa de reglas de negocio (nunca en la capa UI o en la de Datos).

ADO.Net 3.5

Pgina 6

Вам также может понравиться