17 de abril de 2012

SqlTransaction en VS

¿Qué pasa si en alguna en un procesos de actualización de datos de una base de datos falla a la mitad? Lo normal en la mayoría de los casos es deshacer todo lo que se ha hecho y dejar la base de datos como estaba. Este proceso sería muy complicado hacerlo a mano, por no decir imposible. Para esto están las transacciones, que de una manera muy fácil nos ayudan a resolver este tipo de problemas, sobre todo es util cuando hay varias tablas involucradas en los cambios a realizar, pues  las operaciones son indivisibles, lo que significa que o se ejecutan todas las operaciones o no se ejecuta ninguna. En el Caso de las Transacciones con las Bases de Datos, si la Transacción ha dado error se hace un “Rollback” para deshacer todos los cambios.

Aquí ingresaremos datos a una tabla llamada personal dentro de una base de datos llamada empleado, lo primero que hacemos es crear una cadena de conexión y abrir una conexión con ésta. Con esta conexión abierta creamos la transacción (con el método “BeginTransaction”) y ejecutamos la instrucción de insertar datos. Si todo ha ido bien, hacemos un “Commit” de la transacción y si algo ha fallado hacemos un “Rollback”. Es importante hacer un ”Commit” ya que si no, el sistema hará un “Rollback” automáticamente al cerrar la conexión.

este es el diseño del formulario a utilizar tanto en VB como en C#, se usara también un procedimiento almacenado llamado InsertarDatos para guardar los registros en la base de datos



Ejemplo Transacciones en VB

Imports System.Data

Imports System.Data.SqlClient
Imports System.Configuration

Public Class Control
    Dim trans As SqlTransaction = Nothing
    Private Sub BAgregar_Click(sender As System.Object, e As System.EventArgs) Handles BAgregar.Click

        Try
            Using Sql As New SqlConnection(My.Settings.cnn)
                Sql.Open()
                trans = Sql.BeginTransaction(IsolationLevel.ReadCommitted)
                Using cmd As New SqlCommand("InsertarDatos", Sql, trans)
                    cmd.Connection = Sql
                    cmd.CommandType = CommandType.StoredProcedure
                    cmd.Parameters.AddWithValue("@codigo", TNombres.Text)
                    cmd.Parameters.AddWithValue("@nombres", TApellido.Text)
                    cmd.Parameters.AddWithValue("@cargo", TPuesto.Text)
                    cmd.Parameters.AddWithValue("@jefe", TSueldo.Text)
                    cmd.ExecuteNonQuery()
                    trans.Commit()
                End Using
            End Using
        Catch ex As SqlException
            If Not trans Is Nothing Then
                trans.Rollback() 
            End If
            MessageBox.Show(ex.Message)
        End Try
    End Sub
End Class




Ejemplo Transacciones en C#


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Data.SqlClient;

namespace WindowsFormsApplication11
{
    public partial class Form1 : Form
    {
        SqlTransaction trans;
        SqlConnection sql = new SqlConnection(ConfigurationManager.ConnectionStrings["cnn"].ConnectionString);
        SqlCommand cmd;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void BAgregar_Click(object sender, EventArgs e)
        {
            try
            {
                using (sql)
                {
                    sql.Open();
                    trans = sql.BeginTransaction(IsolationLevel.ReadCommitted);
                    using (cmd = new SqlCommand("InsertarDatos", sql, trans))
                    {
                        cmd.CommandType = System.Data.CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@nombre", TNombres.Text);
                        cmd.Parameters.AddWithValue("@apellido", TApellidos.Text);
                        cmd.Parameters.AddWithValue("@puesto", TPuesto.Text);
                        cmd.Parameters.AddWithValue("@sueldo", TSueldo.Text);
                        cmd.ExecuteNonQuery();
                        trans.Commit();
                    }

                }
            }
            catch (Exception ex){
                trans.Rollback();
                MessageBox.Show(ex.Message);
            }
        }
    }
}



 Cómo hemos visto el uso de transacciones desde .NET es muy fácil y hace nuestras aplicaciones más robustas. Pero, ¿qué pasa cuando entran en juego varias bases de datos, o incluso varios gestores de base de datos (varios Sql Server)? Para eso tenemos el TransactionScope, que podemos ver en http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx