Introducción
Este ejemplo nos muestra un Formulario de Pedido usando LINQ, por cuestiones de Documentación, es posible que NO ESTE USANDO CORRECTAMENTE todo el potencial de LINQ, asi que espero sugerencias para mejoras, asi mismo debo decirles que hago un abuso de métodos a nivel de formulario las cuales estarían mejor dentro de clases pero creo que para un inicio esto esta bien y cumple con su objetivo.
Modelo de Base de Datos
Bueno me di la libertad de ponerles el esquema de mi base de datos de pruebas que suelo usar para este tipo de ejemplos.
Obviamente los Tipos de Datos funciones y demas, estan dentro del archivo para descargar, asi que no se preocupen, por cierto me olvidaba, estoy usando Ms SQL Server Express.
Agregando el Objeto LINQ to SQL
Lo primero que debemos hacer es presionar la siguiente combinacion de teclas Ctrl + Shift + A, inmediatamente nos aparecera la siguiente ventana en la cual seleccionaremos la opcion el Elemento LINQ to SQL classes, a la cual le pondremos de nombre "bdVentasLinq.dbml".
A continuación lo que debemos hacer es arrastrar todos Nuestras Tablas de la Base de Datos hacia el Elemento LINQ to SQL, el cual debera quedar de la siguiente forma.
Agregando Clase clsDetalleVenta
A continuacióna gregamos un elemento clase y le damos el nombre de clsDetalleVenta, esta clase nos permitira almacenar el Detalle de un Pedido en especifico.
Public Class clsDetalleVenta Private idProducto As String Private nombreProducto As String Private cantidad As Integer Private precio As Double Private subtotal As Double Private stockArticulo As Double Public Property _stockArticulo() As Integer Get Return stockArticulo End Get Set(ByVal value As Integer) stockArticulo = value End Set End Property Public Property _idProducto() As String Get Return idProducto End Get Set(ByVal value As String) idProducto = value End Set End Property Public Property _nombreProducto() As String Get Return nombreProducto End Get Set(ByVal value As String) nombreProducto = value End Set End Property Public Property _cantidad() As Integer Get Return cantidad End Get Set(ByVal value As Integer) cantidad = value End Set End Property Public Property _precio() As Double Get Return precio End Get Set(ByVal value As Double) precio = value End Set End Property Public Property _subtotal() As Double Get Return subtotal End Get Set(ByVal value As Double) subtotal = value End Set End Property End Class
Y agregamos un modulo donde metere algunas funciones rutinarias, tales como Cuadros de Dialogo y otras cosas que se me ocurran, a este modulo le pondremos como nombre mensajes.
Module mensajes Public Sub msginformacion(ByVal mensaje As String) MessageBox.Show(mensaje, "Sis. Ventas", MessageBoxButtons.OK, _ MessageBoxIcon.Information) End Sub Public Sub msgerror(ByVal mensaje As String) MessageBox.Show("Ocurrio el Error: " & Environment.NewLine _ & mensaje, "Sis. Ventas", _ MessageBoxButtons.OK, MessageBoxIcon.Error) End Sub Public Sub msgpregunta(ByVal mensaje As String) MessageBox.Show(mensaje, "Sis. Ventas", _ MessageBoxButtons.OK, MessageBoxIcon.Question) End Sub End Module
Diseñando el Programa
Diseño del Formulario de Busqueda de Clientes
Ya sabemos que debemos presionar Ctrl + Shift + A, y acontinuacion agregamos un elemento Dialog y le ponemos de nombre frmClientes, el cual luego de agregar los siguientes controles.
- 1 DataGridView
- 1 Label
- 1 TextBox
No menciono los 2 Button ya que etos viene por defecto en el Objeto Dialog, luego de agregados los controles deberia quedar algo asi...
Codificando Nuestro Formulario frmClientes
DataContext:
Se encarga de traducir las peticiones de objetos en consultas SQL (ver el esquema de la arquitectura de LINQ) y devolver los resultados como objetos.
Se encarga de traducir las peticiones de objetos en consultas SQL (ver el esquema de la arquitectura de LINQ) y devolver los resultados como objetos.
Imports System.Windows.Forms Public Class frmClientes 'Instanciamos un objeto de la clase bdVentasLinqDataContext Dim bd As New bdVentasLinqDataContext 'Declaro una variable ID de Forma Publica Public id As String Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles OK_Button.Click 'Extraigo el indice del elemento Seleccionado en el DataGridView Dim row As Integer = Me.DataGridView1.CurrentRow.Index 'Extraigo el elemento situado en la columna DNI_cli id = Me.DataGridView1.Item("DNI_cli", row).Value.ToString 'Se establece como OK el resultado del Cuadro de Dialogo Me.DialogResult = System.Windows.Forms.DialogResult.OK 'Cierro el Formulario Me.Close() End Sub Private Sub Cancel_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Cancel_Button.Click 'Se establece como CANCEL el resultado del Cuadro de Dialogo Me.DialogResult = System.Windows.Forms.DialogResult.Cancel 'Cierro El formulario Me.Close() End Sub Private Sub Dialog1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load 'Este codigo usa una consulta LINQ para obtener una secuencia 'para obtener una secuencia IEnumerable de objetos Clientes Dim query = From cli In bd.Clientes _ Select cli.DNI_cli, cli.ape_cli, cli.nom_cli _ Order By ape_cli Ascending Me.DataGridView1.DataSource = query.ToList End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles TextBox1.TextChanged 'Este codigo usa una consulta LINQ para obtener una secuencia 'para obtener una secuencia IEnumerable de objetos Clientes 'los cuales concuerden con el texto contenido en la caja de 'texto TextBox1 la cual se concatena con el caracter * 'el que nos proporciona la funcionalidad del % en T-SQL 'Todo esto con la finalidad de ser utilizado con la expresion 'LIKE de nuestra consulta LINQ Dim cadena As String cadena = Me.TextBox1.Text & "*" Dim query = From cli In bd.Clientes _ Where cli.ape_cli Like cadena _ Select cli.DNI_cli, cli.ape_cli, cli.nom_cli _ Order By ape_cli Ascending 'Se asocia como Origen de Datos al DataGridView1 'el resultado de la consulta LINQ Me.DataGridView1.DataSource = query.ToList End Sub End Class
Diseño del Formulario de Busqueda de Productos
Ya sabemos que debemos presioanr Ctrl + Shift + A, y acontinuacion agregamos un elemento Dialog y le ponemos de nombre frmProductos, el cual luego de agregar los siguientes controles.
- 1 DataGridView
- 1 Label
- 1 TextBox
No menciono los 2 Button ya que etos viene por defecto en el Objeto Dialog, luego de agregados los controles deberia quedar algo asi...
Codificando Nuestro Formulario frmClientes
Imports System.Windows.Forms Public Class frmProductos 'Todo este proceso es muy similar al del Formulario frmCLientes Dim bd As New bdVentasLinqDataContext Public id As String Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles OK_Button.Click Dim row As Integer = Me.DataGridView1.CurrentRow.Index id = Me.DataGridView1.Item("IdArticulo", row).Value.ToString Me.DialogResult = System.Windows.Forms.DialogResult.OK Me.Close() End Sub Private Sub Cancel_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Cancel_Button.Click Me.DialogResult = System.Windows.Forms.DialogResult.Cancel Me.Close() End Sub Private Sub frmProductos_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load Dim query = From art In bd.Articulos _ Select art.IdArticulo, art.Modelo, art.pre_arti, art.stock_arti _ Order By Modelo Ascending Me.DataGridView1.DataSource = query.ToList End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged Dim cadena As String cadena = Me.TextBox1.Text & "*" Dim query = From art In bd.Articulos _ Where art.Modelo Like cadena _ Select art.IdArticulo, art.Modelo, art.pre_arti, art.stock_arti _ Order By Modelo Ascending Me.DataGridView1.DataSource = query.ToList End Sub End Class
Diseño del Formulario de Pedidos
Agrgamos un Formulario, al cual le agregaremos los siguientes controles:
- 6 TextBox
- 6 Label
- 1 DataGridView
- 8 Button
Y deberian quedar de la siguiente forma:
Codificando Nuestro Formulario frmClientes
Definimos de Manera Global las Siguientes Variables
'Definir el objeto BD de la clase bdVentasLinqDataContext Dim bd As New bdVentasLinqDataContext 'Definir un objeto de la clase clsDetalleVenta Dim objDetVta As clsDetalleVenta Dim nombreArticulo As String Dim idArticulo As String Dim precioArticulo As Double Dim DNI As String Dim stockArticulo As Integer 'Definir una LISTA de Objetos clsDetalleVenta Dim ArrDetVta As New List(Of clsDetalleVenta)
A continuacion codificaremos el Button que se encuentra al lado del TextBox DNI
Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Button1.Click 'Instanciamos un Objeto del Formulario frmClientes Dim dialog As New frmClientes 'Mostramos el Formulario dialog.ShowDialog() 'Si el resultado del Formulario es OK '---------------------------------------------------- 'Si el resultado del Formulario es diferente a OK 'Nos mostrara un mensaje en el que nos indique que no 'hay ningun Cliente Seleccionado If dialog.DialogResult = Windows.Forms.DialogResult.OK Then 'Usamos una instruccion LINQ para seleccionar a un Cliente en Especifico 'El cual lo recuperamos de la variable ID que fue declarada como PUBLICA 'En el Formulario frmClientes Dim query = From qCliente In bd.Clientes _ Where qCliente.DNI_cli = dialog.id _ Select qCliente.DNI_cli, qCliente.ape_cli, qCliente.nom_cli 'Cargamos los valores del resultado de la consulta 'LINQ a los TextBox correspondientes Me.txtDNI.Text = query.ToList.Item(0).DNI_cli.ToString Me.txtNombre.Text = query.ToList.Item(0).nom_cli & " " & _ query.ToList.Item(0).ape_cli DNI = query.ToList.Item(0).DNI_cli.ToString Else mensajes.msginformacion("No ha seleccionado Ningun Cliente") Me.txtDNI.Text = "" Me.txtNombre.Text = "" DNI = "" End If End Sub
Codificaremos el Button que se encuentra al lado del TextBox Nombre del Producto
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Button2.Click 'Se Aplica el mismo Procedimiento que en el Evento Anterior 'para seleccionar un Articulo Dim dialog As New frmProductos dialog.ShowDialog() If dialog.DialogResult = Windows.Forms.DialogResult.OK Then Dim query = From qArti In bd.Articulos _ Where qArti.IdArticulo = dialog.id _ Select qArti.IdArticulo, qArti.Modelo, qArti.pre_arti, qArti.stock_arti Me.txtNombreProducto.Text = query.ToList.Item(0).Modelo.ToString Me.txtPrecioProducto.Text = query.ToList.Item(0).pre_arti.ToString("C") nombreArticulo = query.ToList.Item(0).Modelo.ToString idArticulo = query.ToList.Item(0).IdArticulo.ToString precioArticulo = Convert.ToDouble(query.ToList.Item(0).pre_arti.ToString) stockArticulo = Convert.ToInt32(query.ToList.Item(0).stock_arti.ToString) txtCantidad.Focus() Else mensajes.msginformacion("No ha seleccionado Ningun Producto") Me.txtNombreProducto.Text = "" Me.txtPrecioProducto.Text = "" nombreArticulo = "" idArticulo = "" precioArticulo = "" End If End Sub
Ahora programaremos el Boton Agregar
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click 'Verificamos que el Nombre del Producto, Precio y Cantidad 'NO esten vacios If txtNombreProducto.Text <> "" And txtPrecioProducto.Text <> "" And txtCantidad.Text <> "" Then 'Verificamos que el Stock del Artículo Seleccionado 'NO sea menor que el solicitado If Convert.ToInt32(stockArticulo) < Convert.ToInt32(txtCantidad.Text) Then 'Mostramos una Alerta si la verificacion Anterior es Verdadera mensajes.msginformacion("La Cantidad Requerida es " & _ "Superior a la del Stock") 'Como la Cantidad Solicitada es Mayor a lo que se Tiene en Stock 'Entonces se pregunta si se kiere establecer el STOCk Actual 'Como la nueva cantidad requerida If MessageBox.Show("Desea Establecer el Stock Actual como la " & _ "Nueva Cantidad Requerida", "Sis. Ventas", _ MessageBoxButtons.YesNo) = _ Windows.Forms.DialogResult.Yes Then 'Establecemos la Nueva Cantidad txtCantidad.Text = stockArticulo 'Inicializamos el Objeto de la Clase clsDetalleVenta objDetVta = New clsDetalleVenta 'A continuacion llenamos los valores 'Necesarios para este Objeto objDetVta._cantidad = Convert.ToInt32(txtCantidad.Text) objDetVta._idProducto = idArticulo objDetVta._nombreProducto = nombreArticulo objDetVta._precio = precioArticulo objDetVta._stockArticulo = stockArticulo objDetVta._subtotal = precioArticulo * Convert.ToInt32(txtCantidad.Text) 'En esta parte Verificamos si es que el Aritculo solicitado 'Se encuentra ya en la Lista de Pedidos, de ser Falso 'Lo Agregamos a Nuestros LIST de DetalleVenta If buscarDetVta(ArrDetVta, objDetVta) = False Then 'Agregamos nuestro Pedido al LIST de DetalleVenta ArrDetVta.Add(objDetVta) End If 'Asociamos el LIST de DetalleVenta como origen de 'Datos del DataGridView Me.DataGridView1.DataSource = ArrDetVta Else 'Si no se desea establecer el Stock Actual como 'La nueva cantidad a Solicitar se vuelve al Formulario 'Para escoger un Articulo Button2_Click(Nothing, Nothing) End If Else 'Como la Cantidad Requerida es Menor al Stock Actual 'inicializamos el Objeto de la clase clsDetalleVenta objDetVta = New clsDetalleVenta 'A continuacion llenamos los valores 'Necesarios para este Objeto objDetVta._cantidad = Convert.ToInt32(txtCantidad.Text) objDetVta._idProducto = idArticulo objDetVta._nombreProducto = nombreArticulo objDetVta._precio = precioArticulo objDetVta._stockArticulo = stockArticulo objDetVta._subtotal = precioArticulo * Convert.ToInt32(txtCantidad.Text) 'En esta parte Verificamos si es que el Aritculo solicitado 'Se encuentra ya en la Lista de Pedidos, de ser Falso 'Lo Agregamos a Nuestros LIST de DetalleVenta If buscarDetVta(ArrDetVta, objDetVta) = False Then 'Agregamos nuestro Pedido al LIST de DetalleVenta ArrDetVta.Add(objDetVta) End If 'Asociamos el LIST de DetalleVenta como origen de 'Datos del DataGridView Me.DataGridView1.DataSource = ArrDetVta.ToList End If End If 'Una vez Agregado un Nuevo Detalle para el Pedido 'Limpiamos los textBox Me.limpiar_producto() Button2.Focus() 'Calculamos el Total del Pedido Me.calcular_total() End Sub
Metodo para veirifcar si es que ya se Solicito un Articulo Anteriomente
Public Function buscarDetVta(ByVal array As List(Of clsDetalleVenta), _ ByVal objDV As clsDetalleVenta) As Boolean 'Funcion para verificar si es que ya se solicito un Articulo For Each obj As clsDetalleVenta In array If obj._idProducto = objDV._idProducto Then Dim nCantidad As Integer 'De encontrarse el Arituclo en la Lista de Pedidos 'Lo que se hace es incrementar la Cnatidad Solicitada 'Mas la cantidad Pedida Anteriormente nCantidad = obj._cantidad + objDV._cantidad If nCantidad <= obj._stockArticulo Then obj._cantidad = nCantidad obj._subtotal = obj._precio * obj._cantidad Else mensajes.msgerror("El Stock Actual es insuficiente para el Requerimiento") End If Return True End If Next Return False End Function
Metodo para Limpiar los TextBox Asociados al Articulo
Sub limpiar_producto() 'Metodo para limpiasr TextBox Me.txtCantidad.Clear() Me.txtNombreProducto.Clear() Me.txtPrecioProducto.Clear() End Sub
Metodo para Calcular el Total del Pedido
Sub calcular_total() 'Metodo para Calcular El Total del Pedido Dim sum As Double For Each i As clsDetalleVenta In ArrDetVta sum += i._subtotal Next Me.txtTotal.Text = sum.ToString("C") End Sub
Ahora Programaremos el Boton Eliminar
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Button4.Click 'Removemos un Articulo seleccionado en el DataGridView ArrDetVta.RemoveAt(Me.DataGridView1.CurrentRow.Index) 'Vovlemos a Asociar nuestro LIST como origen de Datos del DataGridView Me.DataGridView1.DataSource = ArrDetVta.ToList 'Volvemos a Calcular el Total del Pedido Me.calcular_total() End Sub
Programamos el Boton Cancelar
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Button5.Click limpiar_cliente() limpiar_producto() limpiar_venta() Me.calcular_total() End Sub
Metodo para limpiar los Controles asociados al Cliente
Sub limpiar_cliente() 'Metodo para limpiar los textBox Asociados al Cliente Me.txtDNI.Clear() Me.txtNombre.Clear() End Sub
Metodo para borrar el Detalle del Pedido
Sub limpiar_venta() 'Limpiamos el LIST usando su Metodo CLEAR ArrDetVta.Clear() 'Vovlemos a Asociar nuestro LIST como origen de Datos del DataGridView Me.DataGridView1.DataSource = ArrDetVta.ToList End Sub
Y por Ultimo y quizas lo mas importante, la codificacion del Boton Grabar
Private Sub btngrabar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles btngrabar.Click 'Aprovechando que nuestra Base de Datos 'Esta relacionada, usaremos a LINQ para que 'Nos haga las Inserciones y actualizaciones 'Que necesitamos Try 'La siguiente Expresion me devuelve un Objeto Cliente 'buscandolo por su id es decir por el Campo DNI_Cli Dim C As Cliente = bd.Clientes.Single(Function(p) p.DNI_cli = Me.txtDNI.Text) 'Creo un nuevo Encabezado de Boleta 'Y procedo a Inicializarlo '------------------------------------------------- Dim EB As New EncabezadoBoleta EB.Fech_Bol = Date.Now EB.Total_Bol = CDec(Me.txtTotal.Text) EB.Anulado = "F" EB.Cliente = C EB.IdCliente = C.IdCliente '-------------------------------------------------- ' ' 'Ya que tengo todo el Detalle del Pedido en un LIST 'Aprovechare este detalle para generar mis Objetos Pedido For Each obj As clsDetalleVenta In ArrDetVta 'Instacion un Objeto Articulo Seleccionandolo 'Por el Campo IdArticulo Dim Art As Articulo = _ bd.Articulos.Single(Function(a) a.IdArticulo = obj._idProducto.ToString()) 'Creo un nuevo Detalle de Boleta 'Y procedo a Inicializarlo Dim DB As New DetalleBoleta DB.Articulo = Art DB.Cant_det = obj._cantidad DB.Importe = obj._subtotal DB.Prec_det = obj._precio 'Agrego el Detalle de Boleta a mi Encabezado de Boleta EB.DetalleBoletas.Add(DB) Next 'Aqui Actualizo la Base De Datos con el Metodo SubmitChanges bd.SubmitChanges() Catch ex As Exception MsgBox(ex.Message) End Try End Sub
Conclusiones
Como vemos, el modelo de programación que hemos usado para hacer todo esto es realmente limpio y orientado a objetos.
Este comentario ha sido eliminado por un administrador del blog.
ResponderEliminarEy justo necesitaba un ejemplo con el DataGrid exactamente igual a este, creo que me servira de mucho, voy a implementarlo en mi sistema a ver que tal me va!!!.. Gracias se nota que esta muy completo y facil de entender.
ResponderEliminarGracias justamento lo que necesito para trabajar en mi registro de ventas gracias..!! sigue asi subiendo mas tutoriales..!!
ResponderEliminares un ejemplo bastante entendible................buenisimo
ResponderEliminarSi que es muy claro lo leo y si mejor no me preocupo y publico, saludos, amigos.
ResponderEliminarEstimado soy el autor de lo que tomaste aqui; al menos pon la fuente de referencia:
ResponderEliminarhttp://www.elguille.info/colabora/2008/jpa_LINQVBNet.htm