Práctica 6
Programación Visual I (Ingeniería en Sistemas)
Programación Visual (Ingeniería en Telemática)
Práctica 6: Acceso a Bases de Datos (Gestión de Facturas)
Objetivos de aprendizaje:
Implementación del acceso a una base de datos de tipo MySQL a través de LINQ to
DataSet.
Gestión de una base de datos de tipo SQL Server a través de LINQ to SQL.
Implementación del acceso a una base de datos de tipo SQL Server utilizando el asistente
de Visual Studio.
Gestión de una base de datos de tipo MySQL mediante código.
Requerimientos Software:
Visual Studio 2010 o superior
Gestor de Bases de Datos MySQL
Gestor de Bases de Datos SQL Server 2008 o superior
Conector de MySQL para .NET
Descripción:
Esta práctica debe gestionar, a través de una interfaz gráfica, la información de las facturas y del
catálogo de productos, de tal manera que toda la información será almacenada en una base de
datos.
Para entrar a la aplicación principal, se debe presentar al usuario un formulario de autenticación
donde debe introducir su usuario y contraseña. Otra opción que tiene la aplicación es que le
permitirá al usuario cambiar su contraseña.
Pasos para el desarrollo de la práctica:
I. GENERAR LA BASE DE DATOS DE TIPO MYSQL.
II. GENERAR LA BASE DE DATOS DE TIPO SQL SERVER.
III. INSTALAR EL CONECTOR DE MYSQL PARA .NET
IV. DISEÑAR EL FORMULARIO PRINCIPAL.
V. DISEÑAR EL FORMULARIO DE AUTENTICACIÓN.
VI. DISEÑAR EL FORMULARIO DE LA GESTIÓN DE LAS FACTURAS.
VII. DISEÑAR EL FORMULARIO DE LA GESTIÓN DEL CATÁLOGO DE PRODUCTOS.
VIII. DISEÑAR EL FORMULARIO DE CAMBIO DE CONTRASEÑA.
IX. INSERTAR EL DIÁLOGO ACERCA DE…
X. ESCRIBIR LA LÓGICA DE LA APLICACIÓN:
1. Código del formulario principal.
2. Código del formulario de las facturas.
3. Código del formulario del catálogo de productos.
4. Código del formulario de cambio de contraseña.
1
Práctica 6
I. GENERAR LA BASE DE DATOS DE TIPO MYSQL.
A continuación se muestra el script para generar la base de datos de tipo MySQL, la que
únicamente contiene una tabla, que almacena los datos de autenticación:
CREATE SCHEMA IF NOT EXISTS `bd_login` DEFAULT CHARACTER SET utf8 COLLATE
utf8_unicode_ci ;
USE `bd_login` ;
-- -----------------------------------------------------
-- Table `bd_login`.`tb_login`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `bd_login`.`tb_login` ;
CREATE TABLE IF NOT EXISTS `bd_login`.`tb_login` (
`nombre` VARCHAR(50) NULL ,
`usuario` VARCHAR(20) NULL ,
`clave` VARCHAR(12) NULL ,
PRIMARY KEY (`usuario`) )
ENGINE = InnoDB;
INSERT INTO `bd_login`.`tb_login` VALUES('Alvaro Altamirano','admin','admin123');
INSERT INTO `bd_login`.`tb_login` VALUES('Maria Gonzalez','mgonzalez','maria123');
INSERT INTO `bd_login`.`tb_login` VALUES('Carlos Perez','cperez','carlos123');
II. GENERAR LA BASE DE DATOS DE TIPO SQL SERVER.
Esta base de datos almacenará la información de las facturas y sus productos, así como el catálogo
de productos. El script para generar la base de datos de tipo SQL Server, es el siguiente:
USE master
GO
2
Práctica 6
-- Drop the database if it already exists
IF EXISTS (
SELECT name
FROM sys.databases
WHERE name = N'bd_ventas'
DROP DATABASE bd_ventas
GO
CREATE DATABASE bd_ventas
GO
USE bd_ventas
GO
CREATE TABLE Catalogo
Codigo int PRIMARY KEY,
Nombre varchar(100) NOT NULL,
Precio float NOT NULL,
);
GO
CREATE TABLE Factura
Codigo int PRIMARY KEY,
Cliente varchar(100) NOT NULL,
Fecha varchar(100) NOT NULL,
);
GO
3
Práctica 6
CREATE TABLE Producto
Id int identity PRIMARY KEY,
Codigo int NOT NULL,
Nombre varchar(100) NOT NULL,
Precio float NOT NULL,
Cantidad int NOT NULL,
Fk_Codigo int FOREIGN KEY REFERENCES Factura(Codigo)
);
GO
INSERT INTO Catalogo VALUES(10,'Televisor',9000);
INSERT INTO Catalogo VALUES(11,'Laptop DELL',15000);
INSERT INTO Catalogo VALUES(12,'Refrigeradora',20000);
INSERT INTO Catalogo VALUES(13,'Abanico',900);
INSERT INTO Catalogo VALUES(14,'Plancha',2000);
INSERT INTO Catalogo VALUES(15,'Cocina',10000);
GO
INSERT INTO Factura VALUES (1, 'Carmen Salinas', '10-Octubre-2015');
INSERT INTO Factura VALUES (2, 'Luis Martinez','15-Mayo-2017');
INSERT INTO Factura VALUES (3, 'Roger Perez','20-Enero-2016');
GO
INSERT INTO Producto (Codigo, Nombre, Precio, Cantidad, Fk_Codigo)
VALUES(10,'Televisor',9000,2,1);
INSERT INTO Producto (Codigo, Nombre, Precio, Cantidad, Fk_Codigo) VALUES(11,'Laptop
DELL',15000,3,1);
INSERT INTO Producto (Codigo, Nombre, Precio, Cantidad, Fk_Codigo)
VALUES(12,'Refrigeradora',20000,4,1);
4
Práctica 6
INSERT INTO Producto (Codigo, Nombre, Precio, Cantidad, Fk_Codigo)
VALUES(13,'Abanico',900,5,2);
INSERT INTO Producto (Codigo, Nombre, Precio, Cantidad, Fk_Codigo)
VALUES(14,'Plancha',2000,6,2);
INSERT INTO Producto (Codigo, Nombre, Precio, Cantidad, Fk_Codigo)
VALUES(10,'Televisor',9000,5,3);
INSERT INTO Producto (Codigo, Nombre, Precio, Cantidad, Fk_Codigo)
VALUES(14,'Plancha',2000,2,3);
GO
III. INSTALAR EL CONECTOR DE MYSQL PARA .NET
Antes de desarrollar la aplicación en Visual Studio, asegúrese que esté instalado el conector de
MySQL para .NET, puede descargarlo de la página siguiente:
https://dev.mysql.com/downloads/connector/net/
Una vez instalado, puede crear el proyecto en Visual Studio. Luego, añada las referencias a
MySQL.Data y MySQL.Data.Client.
IV. DISEÑAR EL FORMULARIO PRINCIPAL.
El formulario principal de la aplicación (formulario padre), debe exponer la siguiente interfaz:
Las órdenes de los diferentes menús deben ser las siguientes:
Archivo: contiene la orden Salir.
Operaciones: contiene las órdenes Facturas, Catálogo y Cambiar contraseña.
5
Práctica 6
Ventana: contiene las órdenes Cascada, Horizontal y Vertical.
Ayuda: contiene la orden Acerca de.
La orden Salir finaliza la aplicación.
La orden Facturas muestra el formulario de las facturas.
La orden Catálogo muestra el formulario de catálogo de productos.
La orden Cambiar Contraseña muestra el formulario de cambio de contraseña.
La orden Cascada organiza los formularios hijos en cascada.
La orden Horizontal organiza los formularios hijos de forma horizontal.
La orden Vertical organiza los formularios hijos de forma vertical.
Recuerde que este formulario es un contenedor de formularios MDI.
V. DISEÑAR EL FORMULARIO DE AUTENTICACIÓN.
Este formulario permite que el usuario introduzca su nombre de usuario y contraseña para poder
entrar al formulario principal. Su interfaz es la siguiente:
El control que muestra la imagen es de tipo PictureBox. La imagen o una similar a ésta puede
buscarla en Google.
6
Práctica 6
VI. DISEÑAR EL FORMULARIO DE LA GESTIÓN DE LAS FACTURAS.
Este formulario nos permitirá visualizar las facturas existentes con sus productos así como ingresar
los datos de una nueva factura. Contiene un control TabControl con dos pestañas: Visualizar y
Nueva. A continuación se muestra una captura de pantalla de ambas pestañas:
7
Práctica 6
En la pestaña Visualizar, al seleccionar el código de una factura, se visualiza el nombre del cliente y
la fecha de compra en la caja de texto multilínea. Los datos de los productos deben ser
visualizados en el DataGridView.
En la pestaña Nueva, se deben introducir los datos de la nueva factura que se quiere guardar, esto
incluye su código, el nombre del cliente, su fecha de compra (control DateTimePicker) así como
cada uno de sus productos con su respectiva cantidad.
Nota: observe que dentro del DataGridView, para seleccionar un producto, se utiliza un
desplegable que contendrá el nombre de todos los productos existentes en el catálogo.
VII. DISEÑAR EL FORMULARIO DE LA GESTIÓN DEL CATÁLOGO DE PRODUCTOS.
Este formulario sirve para mostrar la información de los productos existentes en el catálogo.
También nos permitirá realizar las operaciones de inserción, actualización y eliminación a través
del DataGridView. Su interfaz es la siguiente:
VIII. DISEÑAR EL FORMULARIO DE CAMBIO DE CONTRASEÑA.
Este formulario debe permitirle al usuario cambiar su contraseña.
Su interfaz es la siguiente:
8
Práctica 6
IX. INSERTAR EL DIÁLOGO ACERCA DE…
X. ESCRIBIR LA LÓGICA DE LA APLICACIÓN
a. Código del formulario principal.
Además de los controladores de los eventos Click de cada una de las órdenes de los menús
Archivo, Operaciones, Ventana y Ayuda, se debe escribir el código asociado al evento Load, el
cual debe mostrarle al usuario el formulario de autenticación. Si el usuario ingresa los datos
correctos, puede ingresar al formulario principal, de lo contrario, se cierra la aplicación.
En este caso, la gestión del acceso a la base de datos bd_login de tipo MySQL para verificar que los
datos del usuario son correctos, debe hacerse utilizando la tecnología LINQ to DataSet. A
continuación se muestra un ejemplo de cómo implementarla:
9
Práctica 6
10
Práctica 6
Nota: en el ejemplo la base de datos es de tipo SQL Server, pero la nuestra es de tipo MySQL, por
lo que debemos utilizar las clases MySqlConnection y MySqlDataAdapter. Recuerde que debe
activar los espacios de nombres MySql.Data y MySql.Data.MySqlClient.
b. Código del formulario de las facturas.
Para realizar las operaciones de visualización e inserción de facturas, la gestión a la base de datos
de tipo SQL Server bd_ventas se hará utilizando la tecnología LINQ to SQL. Lo primero que
debemos hacer es añadir una nueva conexión a la base de datos utilizando el “Explorador de
servidores de Visual Studio”:
Una vez creada la conexión, se debe generar el modelo de objetos de la base de datos utilizando el
diseñador relacional de objetos. Para hacer esto, agregue al proyecto un nuevo elemento de tipo
“Clases de LINQ to SQL” y póngale, por ejemplo, el nombre “DatosVentas”. Luego arrastre las
tablas Catalogo, Factura y Producto a la superficie de diseño. El resultado debe ser el siguiente:
11
Práctica 6
Como podrá comprobar, la relación entre las entidades Factura y Producto es de uno a muchos. La
entidad Catalogo es independiente pues sólo contiene la información de los productos que se
pueden vender.
En el evento Load de este formulario, se deben cargar en el combo de la pestaña Visualizar, los
códigos de las facturas existentes.
Una vez hecho esto, si el usuario selecciona un código de factura (evento SelectedIndexChanged),
se muestra el nombre del cliente y la fecha de compra de esa factura en la caja de texto multilínea;
y sus productos en el DataGridView. También se debe mostrar el total de la factura en la caja de
texto correspondiente.
Para realizar todas las operaciones sobre la base de datos utilizaremos la clase derivada de
System.Data.Linq.DataContext, en nuestro caso se llama DatosVentasDataContext.
A continuación se muestra un ejemplo de consultas utilizando LINQ to SQL:
12
Práctica 6
Por otro lado, en la pestaña Nueva, cuando el usuario ingrese los datos de la factura y sus
productos, se deben almacenar dichos datos en las tablas Factura y Producto.
El DataGridView para seleccionar los productos e ingresar su cantidad debe ser configurado en
modo diseño para que tengas 2 columnas: una de tipo DataGridViewComboBoxColumn y la otra
de tipo DataGridViewTextBoxColumn.
El combo del DataGridView debe ser llenado en el evento CellBeginEdit del DataGridView. Para
acceder a este objeto se debe usar la siguiente línea de código:
DataGridViewComboBoxCell combo =
dgvEditProducto.Rows[e.RowIndex].Cells[e.ColumnIndex] as DataGridViewComboBoxCell;
En el evento Click del botón Guardar se deben almacenar los datos ingresados por el usuario en
las tablas Factura y Producto, utilizando los métodos InsertOnSubmit y SubmitChanges. A
continuación se muestra un ejemplo:
using System;
using System.Linq;
namespace LINQtoSQL {
class LinqToSQLCRUD {
static void Main(string[] args) {
string connectString =
System.Configuration.ConfigurationManager.ConnectionStrings["LinqToSQLDBConnecti
onString"].ToString();
LinqToSQLDataContext db = new LinqToSQLDataContext(connectString);
//Create new Employee
Employee newEmployee = new Employee();
newEmployee.Name = "Michael";
13
Práctica 6
newEmployee.Email = "[email protected]";
newEmployee.ContactNo = "343434343";
newEmployee.DepartmentId = 3;
newEmployee.Address = "Michael - USA";
//Add new Employee to database
db.Employees.InsertOnSubmit(newEmployee);
//Save changes to Database.
db.SubmitChanges();
//Get new Inserted Employee
Employee insertedEmployee = db.Employees.FirstOrDefault(e
⇒e.Name.Equals("Michael"));
Console.WriteLine("Employee Id = {0} , Name = {1}, Email = {2},
ContactNo = {3}, Address = {4}",
insertedEmployee.EmployeeId, insertedEmployee.Name,
insertedEmployee.Email,
insertedEmployee.ContactNo, insertedEmployee.Address);
Console.WriteLine("\nPress any key to continue.");
Console.ReadKey();
}
}
}
c. Código del formulario del catálogo de productos.
En este formulario se deben realizar las operaciones de visualización, inserción, actualización y
eliminación de los productos del catálogo a través de un DataGridView. Todas estas operaciones
afectarán a la tabla Catalogo.
En este formulario, se utilizará el asistente de Visual Studio para acceder a dicha tabla. Lo primero
que debemos hacer es arrastrar desde el cuadro de herramientas un objeto de tipo
SqlDataAdapter.
14
Práctica 6
Al abrirse el asistente, debemos seleccionar la conexión a la base de datos SQL Server creada
anteriormente:
Luego elegimos “Usar instrucciones SQL”:
En el generador de consultas, seleccionamos la tabla Catalogo y todos sus campos:
15
Práctica 6
El resultado debería ser el siguiente:
Luego se debe crear el DataSet y asociarlo con el objeto de tipo SqlDataAdapter. Esto debe
hacerse desde la orden “Generar conjunto de datos” del menú “Datos”.
16
Práctica 6
A continuación, se debe establecer como origen de datos del DataGridView al DataSet creado
anteriormente. La propiedad DisplayMember del DataGridView debe tener como valor la tabla
Catalogo.
Por último, se debe escribir el código para afectar a la base de datos si el dataset ha sido
modificado desde el DataGridView. Esto debe hacerse en el evento Click del botón “Guardar
Cambios” y en el evento FormClosing del formulario.
d. Código del formulario de cambio de contraseña
Este formulario le permite el usuario cambiar su contraseña. Debe introducir su clave actual y la
contraseña nueva. Luego, se debe introducir la contraseña nueva una segunda vez y validar que
coincidan, por motivos de verificación.
En este formulario para acceder a la base de datos, utilizaremos el modo código, utilizando la
clase BD_SetGet que se muestra a continuación, la cual nos proporciona los métodos necesarios
para hacer consultas de selección y modificación:
class BD_SetGet
{
private static MySqlConnection conn;
private static MySqlCommand comm;
private static MySqlDataAdapter adapt;
public BD_SetGet()
{
conn = null;
comm = null;
adapt = null;
}
public static bool EstablecerConexion(string cx)
{
try
{
conn = new MySqlConnection(cx);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
return true;
}
public static DataTable EjecutarOrdenSelect(string orden)
{
DataTable table = new DataTable();
try
{
conn.Open();
comm = new MySqlCommand(orden, conn);
adapt = new MySqlDataAdapter();
17
Práctica 6
adapt.SelectCommand = comm;
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapt.Fill(table);
conn.Close();
}
catch(Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
return table;
}
public static int EjecutarOrden(string orden)
{
int n = 0;
try
{
conn.Open();
comm = new MySqlCommand(orden, conn);
n = comm.ExecuteNonQuery();
conn.Close();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
return n;
}
Nota: en toda la aplicación, los formularios hijos deben mostrarse de forma no modal, y si uno de
ellos se encuentra abierto y se intenta volver a abrirlo, no se debe permitir hacer esto, hasta que
se cierre el que esté abierto actualmente, es decir, no debe permitirse tener abierto dos instancias
del mismo formulario al mismo tiempo.
18
Práctica 6
REFERENCIAS
1. Relaciones uno-a-uno y uno-a-muchos en SQL Server:
http://www.tech-recipes.com/rx/56738/one-to-one-one-to-many-table-relationships-in-sql-
server/
2. Tutorial de LINQ to SQL:
http://speakingin.net/tutorial-de-linq-to-sql/
3. DatagridView show records of 2 tables using LINQ:
https://social.msdn.microsoft.com/Forums/en-US/2fbd427f-932b-49b0-8733-
4c51f91e0530/datagridview-show-records-of-2-tables-using-linq?forum=linqtosql
4. [DataGridView] - Uso del DataGridViewComboBoxColumn:
http://ltuttini.blogspot.com/2010/01/datagridview-parte-4-uso-del.html
5. LINQ – SQL:
https://www.tutorialspoint.com/linq/linq_sql.htm
19