25 de julio de 2012

Clase ACME en VB-SQL con SP

Anteriormente mostré un  sencillo-sencillisimo ejemplo de clase ACME para VB, en este ejemplo no se utilizaban procedimientos almacenados para realizar operaciones sobre una tabla en la base de datos:
http://pabletoreto.blogspot.com/2012/07/clase-acme-en-vb.html

Para empezar, puesto que estoy utilizando SQL Xpress 2008, haré los procedimientos almacenados sobre mi base de datos llamada registro utilizando el Microsoft SQl Server Management 2008


esta es la tabla empleado que utilizaremos, se encuentra en la base de datos registro


Lo que sigue es crear una nueva consulta y a continuación esta el código T-SQL para crear los procedimientos almacenados en la base de datos registro sobre la tabla empleado


Procedimiento Almacenado AgregarDatos
Este será el procedimiento almacenado que se utilizara para agregar registros de un nuevo empleado a la base de datos, se tiene un parámetro output que regresa un mensaje dependiendo si la acción de insertar datos se realizó con éxito o si hubo algún problema.
Se muestra el uso de TRANSACTION aunque se trabaja sobre una sola tabla, se puede omitir el uso de este pero en caso se trabaje con base de datos relacionales puede venir en uso.

USE registro
GO
IF OBJECT_ID('AgregarDatos','p')is not null
DROP PROCEDURE AgregarDatos
GO

CREATE PROCEDURE AgregarDatos
@nombres varchar(50),
@cargo varchar(50),
@departamento varchar(50),
@jefe varchar(50),
@mensaje varchar(100) output

AS
SET NOCOUNT ON
BEGIN TRY
BEGIN TRAN
INSERT INTO empleado VALUES(@nombres, @cargo, @departamento, @jefe)
COMMIT
SELECT @mensaje='Registro ingresado correctamente en Base de Datos !!!'
END TRY

BEGIN CATCH
ROLLBACK
SELECT @mensaje='Registro no ingresado en Base de Datos !!!'
END CATCH

Procedimiento Almacenado ModificarDatos
Este será el procedimiento almacenado que se utilizara para modificar registros de empleados existentes en la base de datos, se tiene un parámetro output que regresa un mensaje dependiendo si la acción de modificar datos se realizó con éxito o si hubo algún problema.

USE registro
GO
if OBJECT_ID('ModificarDatos','p') is not null
DROP PROC ModificarDatos
GO

CREATE PROC ModificarDatos
@codigo int,
@nombres varchar(50),
@cargo varchar(50),
@departamento varchar(50),
@jefe varchar(50),
@mensaje varchar(100) output

AS
SET NOCOUNT ON
IF exists (select * from empleado where Codigo=@codigo)
BEGIN TRY
BEGIN TRAN
UPDATE empleado SET Nombres=@nombres, Cargo=@cargo, Departamento=@departamento, Jefe=@jefe WHERE Codigo=@codigo
COMMIT
SET @mensaje='El registro fue actualizado correctamente !!!'
END TRY

BEGIN CATCH
ROLLBACK
SET @mensaje='El registro no fue actualizado !!!'
END CATCH
ELSE
BEGIN
SET @mensaje='El registro no existe en la base de datos !!!'
END

Procedimiento Almacenado EliminarDatos
Este será el procedimiento almacenado que se utilizara para eliminar registros de empleados existentes en la base de datos, se tiene un parámetro output que regresa un mensaje dependiendo si la acción de eliminar datos se realizó con éxito o si hubo algún problema.

USE registro
GO
IF OBJECT_ID('EliminarDatos','p')is not null
DROP PROC EliminarDatos
GO

CREATE PROCEDURE EliminarDatos
@codigo int,
@mensaje varchar(100) output

AS
SET NOCOUNT ON
IF EXISTS (select * from empleado where Codigo=@codigo)
BEGIN TRY
BEGIN TRANSACTION
DELETE FROM empleado WHERE Codigo=@codigo
COMMIT
SELECT @mensaje='Registro eliminado correctamente de Base de Datos !!!'
END TRY

BEGIN CATCH
ROLLBACK
set @mensaje='Registro no fue eliminado de la Base de Datos !!!'
END CATCH
ELSE
BEGIN
SET @mensaje='Registro no se puede eliminar pues no existe !!!'
END

ahora muestro el formulario que utilizare, algo a tomar en cuenta es que los datos de la conexión a la base de datos los guardo en un app.config, aquí dejo el link que lo explica: http://pabletoreto.blogspot.com/search/label/App.Config



Evento Form_Load
Al cargar el formulario lo primero que se hará es llenar el DataGridView con los datos de la tabla empleado y habilitar el Bindingnavigator para poder moverse a través de los registros de la tabla, esto se logra invocando al método CargarDatos el cual además crea un enlace entra el BindingNavigator y los textBox para mostrar la información correspondiente

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        CargarDatos()
End Sub

Función Connectar()
Lo único que hace esta función es realizar la conexión a la base de datos y regresar un objeto tipo SqlConnection obteniendo la información del app.config tal como muestra el connectionstrings

<connectionStrings>
        <add name="conexion" connectionString="Data Source=.\LINGONET;Initial Catalog=registro;Integrated Security=True"
            providerName="System.Data.SqlClient" />
    </connectionStrings>

Y este es el código VB para la función Connectar()

Private Function Connectar() As SqlConnection
     Dim cnn As New SqlConnection(ConfigurationManager.ConnectionStrings("conexion").ConnectionString)
     cnn.Open()
     Return cnn
End Function

Cargar datos de la tabla empleado en DataGridView

Private Sub CargarDatos()
        Dim bs As New BindingSource
        Dim cargardatos As String = "select * from empleado"
        Dim cnn As SqlConnection = Connectar()
        Dim da As New SqlDataAdapter(cargardatos, cnn)
        Dim dt As New DataTable
        da.Fill(dt)
        bs.DataSource = dt
        BindingNavigator1.BindingSource = bs
        DGV.DataSource = bs
        CodigoText.DataBindings.Clear()
        CodigoText.DataBindings.Add(New Binding("text", bs, "Codigo"))
        Noento Form Load()mbresText.DataBindings.Clear()
        NombresText.DataBindings.Add(New Binding("text", bs, "Nombres"))
        CargoText.DataBindings.Clear()
        CargoText.DataBindings.Add(New Binding("text", bs, "cargo"))
        DptoText.DataBindings.Clear()
        DptoText.DataBindings.Add(New Binding("text", bs, "departamento"))
        JefeText.DataBindings.Clear()
        JefeText.DataBindings.Add(New Binding("text", bs, "jefe"))
        cnn.Close()
    End Sub

Evento click botón AgregarRegistro

Private Sub BAgregar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BAgregar.Click
Try
   Dim cnn As SqlConnection = Connectar()
   Dim cmd As New SqlCommand("AgregarDatos", cnn)
   cmd.CommandType = CommandType.StoredProcedure
   cmd.Parameters.Add("@nombres", SqlDbType.VarChar).Value = NombresText.Text
   cmd.Parameters.Add("@cargo", SqlDbType.VarChar).Value = CargoText.Text
   cmd.Parameters.Add("@departamento", SqlDbType.VarChar).Value = DptoText.Text
   cmd.Parameters.Add("@jefe", SqlDbType.VarChar).Value = JefeText.Text
   cmd.Parameters.Add("@mensaje", SqlDbType.VarChar, 100)
   cmd.Parameters("@mensaje").Direction = ParameterDirection.Output
   cmd.ExecuteNonQuery()
   Dim mensaje As String = cmd.Parameters("@mensaje").Value
   MessageBox.Show(mensaje)
   cnn.Close()
   cmd.Dispose()
   CargarDatos()
Catch ex As Exception
   MessageBox.Show(ex.Message)
End Try
End Sub

Evento click botón ModificarRegistro

Private Sub BModificar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BModificar.Click
Try
   Dim cnn As SqlConnection = Connectar()
   Dim cmd As New SqlCommand("ModificarDatos")
   cmd.CommandType = CommandType.StoredProcedure
   cmd.Connection = cnn
   cmd.Parameters.Add("@codigo", SqlDbType.Int).Value = CodigoText.Text
   cmd.Parameters.Add("@nombres", SqlDbType.VarChar).Value = NombresText.Text
   cmd.Parameters.Add("@cargo", SqlDbType.VarChar).Value = CargoText.Text
   cmd.Parameters.Add("@departamento", SqlDbType.VarChar).Value = DptoText.Text
   cmd.Parameters.Add("@jefe", SqlDbType.VarChar).Value = JefeText.Text
   cmd.Parameters.Add("@mensaje", SqlDbType.VarChar, 100)
   cmd.Parameters("@mensaje").Direction = ParameterDirection.Output
   cmd.ExecuteNonQuery()
   Dim mensaje As String = cmd.Parameters("@mensaje").Value
   MessageBox.Show(mensaje)
   cnn.Close()
   cmd.Dispose()
   CargarDatos()
Catch ex As Exception
   MessageBox.Show(ex.Message)
End Try
End Sub

Evento click botón EliminarRegistro

Private Sub BEliminar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BEliminar.Click
Try
   Dim cnn As SqlConnection = Connectar()
   Dim cmd As New SqlCommand("EliminarDatos", cnn)
   cmd.CommandType = CommandType.StoredProcedure
   cmd.Parameters.AddWithValue("@codigo", CodigoText.Text)
   cmd.Parameters.Add("@mensaje", SqlDbType.VarChar, 100)
   cmd.Parameters("@mensaje").Direction = ParameterDirection.Output
   cmd.ExecuteNonQuery()
   Dim mensaje As String = cmd.Parameters("@mensaje").Value
   MessageBox.Show(mensaje)
   cnn.Close()
   cmd.Dispose()
   CargarDatos()
Catch ex As Exception
   MessageBox.Show(ex.Message)
End Try
End Sub


eso es todo :)

Clase ACME en VB-SQL sin SP

Se creara una clase en VB para Actualizar, Modificar, Consultar y Eliminar datos (ACME) sin utilizar procedimientos almacenados, la sencillez de este caso puede parecer hasta casi un insulto para aquellos que piensan que toda aplicación existente en el mundo laboral debe ir satisfactoriamente apegada a una base de datos(me incluyo), por lo que pienso que esta entrada del blog servirá mas para alumnos del cole o aprendices primerizos que para aquellos que ya estén laburreando, igual si les sirve de algo aquí se los dejo.

Para este ejemplo y en mi caso particular me conectare a una base de datos llamada sistema, que contiene una tabla llamada empleado, con tres campos a utilizar: dui(PK), nombres(varchar(50)) y cargo(varchar(50)).

Ustedes pueden utilizar la base que quieran o que deban para probar el ejemplo, lo único a tener en cuenta es que se utilizara un app.config para guardar los datos de la cadena de conexión así que en caso no sepan como hacerlo sera útil que vean esta entrada sobre el app.config:   http://pabletoreto.blogspot.com/search/label/App.Config

Logrando lo anterior, mi app.config queda de la siguiente manera, con el nombre: conexión, servidor local y  base de datos: sistema 

    <connectionStrings>
        <add name="conexion" connectionString="Data Source=.\LINGONET;Initial Catalog=sistema;Integrated Security=True"
            providerName="System.Data.SqlClient"
    <connectionStrings>

ahora se debe agregar una clase a nuestro proyecto de VB, en mi caso llame a la clase ACME, se importaran los siguientes espacios de nombre

Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration


y se declaran las variables necesarias estableciendo la cadena de conexión:

Dim sql As New SqlConnection(ConfigurationManager.ConnectionStrings("conexion").ConnectionString)
    Dim cmd As SqlCommand
    Dim da As SqlDataAdapter
    Dim dt As DataTable
    Dim bs As BindingSource

Ahora viene la parte del ACME, recuerden que el dui es PK y que se trabaja en una tabla llamada empleado sobre los campos dui, nombres y cargo, ademas que no se utilizan procedimientos almacenados sino mas bien se "carga" la sentencia sql en cada función dependiendo de los datos que reciba

En todas las funciones se utiliza un Try-Catch para manejar la cadena de conexión con lo que se me facilita el obtener los errores, ademas se utiliza el command en la variable cmd (cmd = new SqlCommand) que recibe los datos por parámetros y el cual al final de la instrucción es destruido 

Public Sub AgregarDatos(ByVal dui, ByVal nombres, ByVal cargo)
        Try
            sql.Open()
            cmd = New SqlCommand
            cmd.Connection = sql
            cmd.CommandText = "insert into empleado(DUI, nombres, cargo) values (@dui, @nombres, @cargo)"
            cmd.Parameters.AddWithValue("@dui", dui)
            cmd.Parameters.AddWithValue("@nombres", nombres)
            cmd.Parameters.AddWithValue("@cargo", cargo)
            cmd.ExecuteNonQuery()
            MessageBox.Show("datos ingresados eficientemente")
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        cmd.Dispose()
        sql.Close()
    End Sub

    Public Sub ModificarDatos(ByVal dui, ByVal nombres, ByVal cargo)

        Try
            sql.Open()
            cmd = New SqlCommand
            cmd.Connection = sql
            cmd.CommandText = "update empleado SET nombres = @nombres, cargo=@cargo where dui = @dui"
            cmd.Parameters.AddWithValue("@dui", dui)
            cmd.Parameters.AddWithValue("@nombres", nombres)
            cmd.Parameters.AddWithValue("@cargo", cargo)
            cmd.ExecuteNonQuery()
            MessageBox.Show("Dato modificado satisfactoriamente")
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        Finally
            sql.Close()
            cmd.Dispose()
        End Try
    End Sub

    Public Sub EliminarDatos(ByVal dui)
        Try
            sql.Open()
            cmd = New SqlCommand
            cmd.Connection = sql
            cmd.CommandText = "delete from empleado where dui=@id"
            cmd.Parameters.AddWithValue("@id", dui)
            cmd.ExecuteNonQuery()
            MessageBox.Show("dato eliminado correctamente")
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        sql.Close()
        cmd.Dispose()
    End Sub

    Public Function ConsultarDatos() As BindingSource
        Try
            sql.Open()
            da = New SqlDataAdapter("select * from empleado", sql)
            dt = New DataTable
            bs = New BindingSource
            da.Fill(dt)
            bs.DataSource = dt
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        sql.Close()
        da.Dispose()
        Return bs
    End Function


ahora viene la parte del formulario, en mi caso le llame ACME_VB.vb y esta es la apariencia, tiene un DataGridView, un BindingNavigator, 4 botones con las funciones ACME y tres textbox para los campos de la tabla que se van a utilizar...ojo se van a cargar los datos en el DataGridView y se enlazaran con los textbox y con el BindingNavigator al cargar el formulario :)


La referencia a la clase ACME desde el código del formulario y el BindingSource a ocupar se declaran así:

Dim clase As New ACME
Dim bs As BindingSource


ahora, al cargar el formulario invoco a un metodo llamado refrescar(), lo que hace es mostrar los datos en el dataGridView, en los textbox y en el BindingNavigator al cargar el formulario así:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        refrescar()
    End Sub


Private Sub refrescar()
        bs = New BindingSource
        bs = clase.ConsultarDatos
        DataGridView1.DataSource = bs
        BindingNavigator1.BindingSource = bs
        DUIText.DataBindings.Clear()
        DUIText.DataBindings.Add(New Binding("text", bs, "dui"))
        NombreText.DataBindings.Clear()
        NombreText.DataBindings.Add(New Binding("text", bs, "nombres"))
        CargoText.DataBindings.Clear()
        CargoText.DataBindings.Add(New Binding("text", bs, "cargo"))
    End Sub


bueno y el codigo completo del form es este

Public Class ACME_VB
    Dim clase As New ACME
    Dim bs As BindingSource

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        refrescar()
    End Sub

    Private Sub AgregarDatos_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AgregarDatos.Click
        clase.AgregarDatos(DUIText.Text, NombreText.Text, CargoText.Text)
        DataGridView1.DataSource = clase.ConsultarDatos
    End Sub

    Private Sub Consultar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Consultar.Click
        refrescar()
    End Sub

    Private Sub Modificar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Modificar.Click
        clase.ModificarDatos(DUIText.Text, NombreText.Text, CargoText.Text)
        DataGridView1.DataSource = clase.ConsultarDatos
    End Sub

    Private Sub Eliminar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Eliminar.Click
        clase.EliminarDatos(DUIText.Text)
        DataGridView1.DataSource = clase.ConsultarDatos
    End Sub

    Private Sub refrescar()
        bs = New BindingSource
        bs = clase.ConsultarDatos
        DataGridView1.DataSource = bs
        BindingNavigator1.BindingSource = bs
        DUIText.DataBindings.Clear()
        DUIText.DataBindings.Add(New Binding("text", bs, "dui"))
        NombreText.DataBindings.Clear()
        NombreText.DataBindings.Add(New Binding("text", bs, "nombres"))
        CargoText.DataBindings.Clear()
        CargoText.DataBindings.Add(New Binding("text", bs, "cargo"))
    End Sub

End Class