Cómo usar el OCR PetaPoco para accesos (insert, select, update, delete) a servidor de MySQL/MariaDB con Visual Studio .Net y C# (CSharp). PetaPoco admite otros motores de base de datos como Oracle, SQL Server, Firebird, SQLite, MS Access, PostgreSQL, etc.). PetaPoco es un mini ORM (Object–role modeling) que nos permitirá realizar tareas de acceso a base de datos de forma muy sencilla y eficiente. Como ejemplo, mostramos un formulario que permite añadir, eliminar, modificar y listar facturas.
- Preparar tabla en base de datos MariaDB MySQL.
- Paquete de acceso nativo al servidor MySQL MariaDB con C#.
- Instalar PetaPoco en nuestro proyecto Visual Studio .Net CSharp.
- Agregar clases para la aplicación de ejemplo de gestión de facturas con MariaDB MySQL y PetaPoco en C#.
- Crear formulario con componentes para acceso a base de datos y tabla de facturas.
- La aplicación C# de ejemplo para insertar, modificar, listar y eliminar facturas con PetaPoco y CSharp.
- Descarga del código fuente completo de la aplicación de ejemplo de gestión de facturas en C Sharp.
Preparar tabla en base de datos MariaDB MySQL
Para el ejemplo de acceso a servidor MySQL MariaDB con PetaPoco, usaremos una tabla con la siguiente estructura (script SQL de creación de tabla):
1 2 3 4 5 6 7 8 |
CREATE TABLE `facturas`.`factura` ( `codigo` INT NOT NULL AUTO_INCREMENT, `fecha` DATETIME NULL, `cliente` VARCHAR(150) NULL, `importe` DECIMAL(10,2) NULL, `numero` VARCHAR(20) NULL, `observacion` TEXT NULL, PRIMARY KEY (`codigo`)); |
Dispondremos, por lo tanto, de una tabla llamada «fatura» con los campos: codigo (autoincremento y clave primaria), fecha, cliente, importe, numero y observacion.
Como es lógico, dispondremos de un servidor de MySQL Server o MariaDB Server, con dicha tabla creada. En el siguiente artículo explicamos cómo montar un servidor de base de datos MySQL MariaDB en Linux:
Paquete de acceso nativo al servidor MySQL MariaDB con C#
PetaPoco no incluye el acceso en sí al servidor correspondiente de base de datos. Necesitaremos por lo tanto el paquete correspondiente para acceso nativo al servidor que queramos usar de base de datos, en nuestro caso MySQL Server o MariaDB Server.
En el siguiente enlace explicamos cómo usar el paquete para Visual Studio .Net CSharp de MySQL, disponible en su web oficial:
Instalar PetaPoco en nuestro proyecto Visual Studio .Net CSharp
Crearemos, si no lo hemos hecho aún, un proyecto Visual Studio .Net C# (CSharp):
Introduciremos el nombre del proyecto:
Elegiremos la versión de .NET 6.0 (la última disponible):
Para instalar el paquete PetaPoco, desde nuestro proyecto, pulsaremos en el menú «Herramientas» y en «Administrador de paquetes NuGet » – «Administrar paquetes NuGet para la solución…»:
Pulsaremos en «Examniar» [1], escribiremos «petapoco» en buscar [2]. Seleccionaremos «PetaPoco.Compiled» versión 6.0.566 [3]. Marcaremos el proyecto donde se instalará [4] y pulsaremos en «Instalar» [5]:
Una vez instalado nos indicará los paquetes instalados:
- PetaPoco.Compiled.6.0.566.
- System.Reflection.Emit.ILGeneration.4.7.0.
- System.Reflection.Emit.Lighwight.4.7.0.
Pulsaremos «Aceptar» y ya tendremos instalado el paquete PetaPoco para nuestra proyecto C# .Net:
En las dependencias de paquetes de nuestra solución nos habrá añadido «PetaPoco.Compiled»:
Agregar clases para la aplicación de ejemplo de gestión de facturas con MariaDB MySQL y PetaPoco en C#
Agregaremos a nuestro proyecto las clases necesarias y su código para realizar todas las tareas de la aplicación: guardar en fichero de configuración los datos de acceso al servidor, cifrar contraseña, guardar datos de log (para depuración), acceso a la base de datos MariaDB o MySQL con PetaPoco, tabla de facturas, métodos para listar e insertar facturas y clientes, etc..
Para añadir una clase, desde Visual Studio .Net, con nuestro proyecto abierto, pulsaremos con el botón derecho sobre la solución y elegiremos «Agregar» – «Clase…»:
Empezaremos por crear las clases con las utilidades necesarias para el resto de clases. Empezaremos por la clase que escribirá en fichero de log cualquier error o dato que queramos almacenar para depuración. Esta clase se llamará Log y tendrá el siguiente código fuente C#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
namespace ProyectoAAccesoMySQLPetaPoco { static class Log { //Guardar mensaje en fichero de texto o también mostrarlo por consola public static void EsLog(string mensaje, Boolean mostrarConsola) { mensaje = QuitarSaltos(mensaje); if (mostrarConsola) MonstrarMensajeConsola(mensaje); EscribirLineaFichero(mensaje); } //Muestra el mensaje por consola MS-DOS (solo para aplicaciones de consola) private static void MonstrarMensajeConsola(string mensaje) { Console.WriteLine($"{DateTime.Now:dd/MM/yyyy hh:mm:ss} {mensaje}"); } //Escribe el mensaje en un fichero en la carpeta del ejecutable private static void EscribirLineaFichero(string mensaje) { try { FileStream fs = new(@AppDomain.CurrentDomain.BaseDirectory + "estado.log", FileMode.OpenOrCreate, FileAccess.Write); StreamWriter m_streamWriter = new(fs); m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); m_streamWriter.WriteLine($"{DateTime.Now:dd/MM/yyyy hh:mm:ss} {mensaje}"); m_streamWriter.Flush(); m_streamWriter.Close(); } catch { //Silenciosa } } //Quita posibles saltos de línea del mensaje private static string QuitarSaltos (string mensaje) { mensaje = mensaje.Replace(Environment.NewLine, " | "); mensaje = mensaje.Replace("\r\n", " | ").Replace("\n", " | ").Replace("\r", " | "); return mensaje; } } } |
Crearemos otra clase, llamada Config, que será la que escribirá en fichero de configuración los datos de acceso al servidor de base de datos (IP, usuario, contraseña, etc.), con el siguiente código fuente C Sharp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
using System.Configuration; namespace ProyectoAAccesoMySQLPetaPoco { static class Config { //Lee un valor de una clave en el fichero de configuración XML de la aplicación public static string Leer(string clave) { try { return ConfigurationManager.AppSettings[clave] ?? ""; } catch (Exception error) { Log.EsLog ($"Error al leer valor de configuración: {error.GetType()} {error.Message}", false); return ""; } } //Guarda un valor en una clave en el fichero de configuración XML de la aplicación public static void Guardar(string clave, string valor) { try { Configuration ficheroConfXML = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); //Eliminamos la clave actual (si existe), de lo contrario los valores //se irán acumulando separados por coma ficheroConfXML.AppSettings.Settings.Remove(clave); //Asignamos el valor en la clave indicada ficheroConfXML.AppSettings.Settings.Add(clave, valor); //Guardamos los cambios definitivamente en el fichero de configuración ficheroConfXML.Save(ConfigurationSaveMode.Modified); } catch (Exception error) { Log.EsLog($"Error al guardar valor de configuración: {error.GetType()} {error.Message}", false); } } } } |
Añadiremos otra clase, con el nombre Cifrar, que será la encargada de cifrar la contraseña para guardarla en el fichero de configuración, tendrá el siguiente código fuente C Sharp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
namespace ProyectoAAccesoMySQLPetaPoco { using System; using System.IO; using System.Security.Cryptography; using System.Text; static class Cifrar { public static string CifrarAES(string textoCifrar, string palabraPaso, string valorRGBSalt, string algoritmoEncriptacionHASH, int iteraciones, string vectorInicial, int tamanoClave) { try { byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(vectorInicial); byte[] saltValueBytes = Encoding.ASCII.GetBytes(valorRGBSalt); byte[] plainTextBytes = Encoding.UTF8.GetBytes(textoCifrar); PasswordDeriveBytes password = new PasswordDeriveBytes(palabraPaso, saltValueBytes, algoritmoEncriptacionHASH, iteraciones); byte[] keyBytes = password.GetBytes(tamanoClave / 8); RijndaelManaged symmetricKey = new RijndaelManaged(); symmetricKey.Mode = CipherMode.CBC; ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, InitialVectorBytes); MemoryStream memoryStream = new MemoryStream(); CryptoStream cryptoStream = new(memoryStream, encryptor, CryptoStreamMode.Write); cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); cryptoStream.FlushFinalBlock(); byte[] cipherTextBytes = memoryStream.ToArray(); memoryStream.Close(); cryptoStream.Close(); string textoCifradoFinal = Convert.ToBase64String(cipherTextBytes); return textoCifradoFinal; } catch { return ""; } } public static string DescifrarAES(string textoCifrado, string palabraPaso, string valorRGBSalt, string algoritmoEncriptacionHASH, int iteraciones, string vectorInicial, int tamanoClave) { try { byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(vectorInicial); byte[] saltValueBytes = Encoding.ASCII.GetBytes(valorRGBSalt); byte[] cipherTextBytes = Convert.FromBase64String(textoCifrado); PasswordDeriveBytes password = new(palabraPaso, saltValueBytes, algoritmoEncriptacionHASH, iteraciones); byte[] keyBytes = password.GetBytes(tamanoClave / 8); RijndaelManaged symmetricKey = new RijndaelManaged(); symmetricKey.Mode = CipherMode.CBC; ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, InitialVectorBytes); MemoryStream memoryStream = new MemoryStream(cipherTextBytes); CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); byte[] plainTextBytes = new byte[cipherTextBytes.Length]; int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); memoryStream.Close(); cryptoStream.Close(); string textoDescifradoFinal = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); return textoDescifradoFinal; } catch { return ""; } } } } |
Crearemos la clase de acceso a la base de datos. Esta clase será la que contenga los métodos de conexión con el servidor de base de datos. Lo habitual será obtener los datos de acceso al servidor de base de datos desde un fichero de configuración de la aplicación, usando la clase anterior Config. La clase para acceso al servidor de base de datos se llamará Peta y tendrá el siguiente código C Sharp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
namespace ProyectoAAccesoMySQLPetaPoco { using MySql.Data.MySqlClient; using PetaPoco; using System; using System.Data; using System.Threading; public sealed class Peta { private static readonly Lazy<Peta> lazy = new Lazy<Peta>(() => new Peta()); private readonly Database _database; public static Database BD => Instance.GetDatabase(); private Peta() { string servidor, puerto, bd, usuario, contrasena; servidor = Config.Leer("Servidor"); puerto = Config.Leer("Puerto"); bd = Config.Leer("Base de datos"); usuario = Config.Leer("Usuario"); contrasena = Cifrar.DescifrarAES(Config.Leer("Contraseña"), "Encriptad0", "SalT", "MD5", 22, "1234567891234567", 128); string connStr = String.Format("server={0};port={1};user id={2}; password={3}; " + "database={4}; pooling=true;" + "Allow Zero Datetime=False;Convert Zero Datetime=True;Connect Timeout=10;ConnectionLifetime=60", servidor, puerto, usuario, contrasena, bd); _ = new MySqlConnectionStringBuilder(connStr) { AllowZeroDateTime = true, ConvertZeroDateTime = true }; _database = new Database(new MySqlConnection(connStr))//builder.ConnectionString, "MySql.Data.MySqlClient") { EnableAutoSelect = false, EnableNamedParams = true, // ForceDateTimesToUtc = true, CommandTimeout = 60 }; //_database.KeepConnectionAlive = true; } public static Peta Instance { get { return lazy.Value; } } //Conexión con el servidor de base de datos public Database GetDatabase() { int intentosMáximos = 5; while (true) { try { if (_database.Connection.State == ConnectionState.Closed) { _database.Connection.Open(); } return _database; } catch (MySqlException ex) { //Si se produce un error de conexión de tipo 0, 1042, 1044 o 1045 se realizan 5 intentos de conexión if (intentosMáximos > 0 && (ex.Number == 0 || ex.Number == 1042 || ex.Number == 1043 || ex.Number == 1044 || ex.Number == 1045)) { intentosMáximos--; Thread.Sleep(50); } else { throw; } } catch (Exception ex) { Log.EsLog($"Error al conectar al servidor de base de datos: {ex.Message}", false); MessageBox.Show($"Error al conectar al servidor de base de datos. Error: {ex.Message}", "Error al conectar a la BD...",MessageBoxButtons.OK,MessageBoxIcon.Error); } } } } } |
Crearemos la clase para la tabla de facturas de la base de datos, la llamaremos BDFacturas y tendrá el siguiente código fuente C#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
using PetaPoco; namespace ProyectoAAccesoMySQLPetaPoco { [TableName("factura")] [PrimaryKey("codigo")] public class BDFactura { [Column("codigo")] public int Codigo { get; set; } [Column("fecha")] public DateTime fecha { get; set; } [Column("cliente")] public string cliente { get; set; } [Column("importe")] public decimal importe { get; set; } [Column("observacion")] public string observacion { get; set; } [Column("numero")] public string numero { get; set; } //Constructor vacío para instanciar sin argumentos public BDFactura() { Codigo = 0; fecha = DateTime.Now; cliente = ""; importe = 0; observacion = ""; numero = ""; } //Constructor con clase de BDFactura para asignar los valores //al instancionar la clase con este constructor public BDFactura(BDFactura elm, int codigoElemento) { Codigo = codigoElemento; fecha = elm.fecha; cliente = elm.cliente; importe = elm.importe; observacion = elm.observacion; numero = elm.numero; } } } |
Crearemos una última clase, llamada Pro, que será la que contenga todos los métodos que utilizaremos en la aplicación para insertar facturas, obtener lista de facturas, obtener lista de clientes, etc.. El código fuente C Sharp será:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
namespace ProyectoAAccesoMySQLPetaPoco { class Pro { //Método que obtiene una lista de clientes de la tabla "factura", campo "cliente" //Se le pasa como parámetro un ComboBox y es ahí donde mostrará el resultado public static void ObtenerClientes (ComboBox lista) { try { //Cargamos la lista de clientes en el desplegable List<BDFactura> clientes = Peta.BD.Fetch<BDFactura>("select distinct(cliente) from factura order by cliente"); foreach (var clienteActual in clientes) { lista.Items.Add(clienteActual.cliente); } } catch (Exception ex) { MessageBox.Show($"Error al obtener clientes de las facturas. Error: {ex.Message}", "Error al obtener clientes...", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //Método que obtiene todas las facturas de la tabla "factura" //Se le pasa como parámetro un ListView y es ahí donde mostrará el resultado public static void ObtenerFacturas (ListView lista) { try { //Establecemos las propiedades del ListView lista.Clear(); lista.View = View.Details; lista.GridLines = true; lista.FullRowSelect = true; var lFacturas = ObtenerFacturas(); if (lFacturas != null) { //Cargamos una lista de elementos de la clase BDFactura con los registros de la tabla "factura" List<BDFactura> facturas = lFacturas; //Añadimos las columnas al ListView con su formato para mostrar los campos de los registros de la tabla factura lista.Columns.Add("Código", 90, HorizontalAlignment.Left); lista.Columns.Add("Cliente", 330, HorizontalAlignment.Left); lista.Columns.Add("Importe", 120, HorizontalAlignment.Right); lista.Columns.Add("Número", 100, HorizontalAlignment.Left); lista.Columns.Add("Fecha", 180, HorizontalAlignment.Left); lista.Columns.Add("Observación", 280, HorizontalAlignment.Left); //Recorremos cada registro de la tabla factura para añadir una línea al ListView _ = new ListViewItem(); foreach (var factActual in facturas) { ListViewItem filasListView = new(factActual.Codigo.ToString()); filasListView.SubItems.Add(factActual.cliente); filasListView.SubItems.Add(factActual.importe.ToString()); filasListView.SubItems.Add(factActual.numero); filasListView.SubItems.Add(factActual.fecha.ToString()); filasListView.SubItems.Add(factActual.observacion); lista.Items.Add(filasListView); } } } catch (Exception ex) { MessageBox.Show($"Error al obtener las facturas. Error: {ex.Message}", "Error al obtener facturas...", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //Obtiene una lista de facturas de la base de datos usando PetaPoco, la devuelve en una lista de objetos de la clase BDFacturas //Ordenamos el resultado para que la primera fila muestre la última factura y así sucesivamente public static List<BDFactura>? ObtenerFacturas() { try { List<BDFactura> facturas = Peta.BD.Fetch<BDFactura>("select * from factura order by codigo desc"); return facturas; } catch (Exception ex) { MessageBox.Show($"Error al obtener las facturas de la base de datos. Error: {ex.Message}", "Error al obtener facturas...", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } } //Obtiene una factura filtrada por código (clave primaria), la devuelve como un objeto de la clase BDFacturas public static BDFactura? ObtenerFactura(int codigo) { try { BDFactura factura = Peta.BD.First<BDFactura>("select * from factura where codigo = @0", codigo); return factura; } catch (Exception ex) { MessageBox.Show($"Error al obtener la factura con código [{codigo}] de la base de datos. Error: {ex.Message}", "Error al obtener factura...", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } } } } |
Crear formulario con componentes para acceso a base de datos y tabla de facturas
Añadiremos en el formulario principal de nuestra aplicación C# los siguientes componentes, para acceso al servidor de base de datos y para insertar, mostrar, eliminar y modificar facturas:
A continuación mostraremos el código fuente de cada botón del formulario. Empezaremos por el botón «Guardar configuración«, que tendrá siguiente código fuente en su evento Click:
1 2 3 4 5 6 7 8 |
private void BtGuardarConfiguracion_Click(object sender, EventArgs e) { Config.Guardar("Servidor", txtServidor.Text); Config.Guardar("Usuario", txtUsuario.Text); Config.Guardar("Contraseña", Cifrar.CifrarAES(txtContraseña.Text, "Encriptad0", "SalT", "MD5", 22, "1234567891234567", 128)); Config.Guardar("Puerto", txtPuerto.Text); Config.Guardar("Base de datos", txtBaseDatos.Text); } |
El botón «Probar conexión» tendrá el siguiente código fuente en su evento Click:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
private void BtProbarConexion_Click(object sender, EventArgs e) { try { if (Peta.BD.Connection.State == System.Data.ConnectionState.Open) MessageBox.Show($"Ya se estableció la conexión con el servidor {txtServidor.Text}.", "Conexión ya establecida...", MessageBoxButtons.OK, MessageBoxIcon.Information); else { Peta.BD.Connection.Open(); MessageBox.Show($"Conexión realizada correctamente al servidor de base de datos {txtServidor.Text}.", "Conexión con servidor de BD...", MessageBoxButtons.OK, MessageBoxIcon.Information); } } catch (Exception ex) { MessageBox.Show($"Error al conectar a servidor de base de datos: {ex.Message}", "Error de conexión...", MessageBoxButtons.OK, MessageBoxIcon.Error); } } |
El botón «Añadir» tendrá el siguiente código C# en su evento Click:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
private void BtInsertarFactura_Click(object sender, EventArgs e) { //Comprobamos que se hayan introducido los datos básicos de la factura bool continuar = txtImporte.Text == "" ? false : true && txtFecha.Text == "" ? false : true && lsCliente.Text == "" ? false : true; if (continuar) { try { //Creamos un elemento de la clase BDFactura y le asignamos los valores de los campos BDFactura factura = new() { fecha = txtFecha.Value, cliente = lsCliente.Text, importe = Convert.ToDecimal(txtImporte.Text), observacion = txtObservacion.Text, numero = txtNumero.Text }; //Si es una modificación, el TextBox "txtCodigo" tendrá el valor del código (clave primaria) de la factura a modificar //Por lo tanto, lo añadimos al objeto "factura" para la modificación if (txtCodigo.Text != "") factura.Codigo = Convert.ToInt16(txtCodigo.Text); //Si es inserción de factura if (BtInsertarFactura.Text == "Añadir") { //Insertamos la factura en base de datos mediante PetaPoco var resultado = Peta.BD.Insert(factura); MessageBox.Show($"Factura con código [{resultado}] insertada correctamente.", "Factura insertada...", MessageBoxButtons.OK, MessageBoxIcon.Information); } //Si es una modificación de una factura existente if (BtInsertarFactura.Text == "Modificar") { var resultado = Peta.BD.Update(factura); if (resultado > 0) { MessageBox.Show($"Factura con número [{factura.numero}] modificada correctamente.", "Factura modificada...", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { MessageBox.Show($"Ha habido algún error al modificar la factura [{factura.numero}].", "Error al modificar factura...", MessageBoxButtons.OK, MessageBoxIcon.Error); } } //Borramos los datos del formulario tras insertar/modificar la factura txtFecha.Value = DateTime.Now; lsCliente.Text = ""; txtImporte.Text = ""; txtObservacion.Text = ""; txtNumero.Text = ""; txtCodigo.Text = ""; txtFecha.Focus(); //Refrescamos el ComboBox de clientes por si se ha añadido un cliente no existente lsCliente.Items.Clear(); Pro.ObtenerClientes(lsCliente); //Refrescamos la lista de facturas en el ListView con la nueva factura Pro.ObtenerFacturas(lsFacturas); //Dejamos el botón en modo "Añadir" BtInsertarFactura.Text = "Añadir"; GFactura.Text = "Añadir factura"; } catch (Exception ex) { MessageBox.Show($"Error al insertar/modificar factura. Error: {ex.Message}", "Error al insertar/modificar factura...", MessageBoxButtons.OK, MessageBoxIcon.Error); } } else MessageBox.Show($"Faltan datos por introducir. Debe indicar la fecha, el cliente y el importe de la factura.", "Faltan datos...", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } |
El botón «Refrescar» tendrá el siguiente código C#:
1 2 3 4 |
private void BtObtener_Click(object sender, EventArgs e) { Pro.ObtenerFacturas(lsFacturas); } |
El botón «Modificar» tendrá el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
private void BtModificar_Click(object sender, EventArgs e) { if (lsFacturas.SelectedItems.Count >= 1) { GFactura.Text = "Modificar factura"; BtInsertarFactura.Text = "Modificar"; //Obtenemos el código (clave primaria) del registro (factura) elegido por el usuario en el ListView int codigo = Convert.ToInt16(lsFacturas.SelectedItems[0].SubItems[0].Text); //Buscamos el registro en la tabla factura para obtener los datos y mostrarlos var lFacturas = Pro.ObtenerFactura(codigo: codigo); if (lFacturas != null) { BDFactura factura = lFacturas; txtFecha.Value = factura.fecha; lsCliente.Text = factura.cliente; txtImporte.Text = factura.importe.ToString(); txtNumero.Text = factura.numero; txtObservacion.Text = factura.observacion; txtCodigo.Text = codigo.ToString(); } else { MessageBox.Show($"No se ha encontrado la factura con código [{codigo}] en la base de datos.", "Factura no encontrada...", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } else { MessageBox.Show("No ha seleccionado una factura a modificar.", "Selección de factura...", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } |
Y el botón «Eliminar» tendrá el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
private void btEliminar_Click(object sender, EventArgs e) { if (lsFacturas.SelectedItems.Count >= 1) { //Obtenemos el código (clave primaria) del registro (factura) elegido por el usuario en el ListView int codigo = Convert.ToInt16(lsFacturas.SelectedItems[0].SubItems[0].Text); if (MessageBox.Show($"¿Desea eliminar la factura con código [{codigo}]?", "Eliminar factura...", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { //Eliminamos la factura en la base de datos con PetaPoco int resultado = Peta.BD.Delete<BDFactura>(codigo); if (resultado > 0) { //Recargamos la lista de facturas en el ListView para que desaparezca la eliminada BtObtener_Click(sender, e); MessageBox.Show($"Factura con código [{codigo}] eliminada correctamente.", "Factura eliminada...", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { MessageBox.Show($"La factura con código [{codigo}] no se ha encontrado.", "Factura no encontrada...", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } } else { MessageBox.Show("No ha seleccionado una factura a eliminar.", "Selección de factura...", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } |
La aplicación C# de ejemplo para insertar, modificar, listar y eliminar facturas con PetaPoco y CSharp
Ejecutaremos la aplicación de gestión de facturas con PetaPoco y C#. Introduciremos los datos de acceso al servidor de base de datos MySQL/MariaDB: servidor (IP o nombre DNS), puerto (habitualmente el 3306), usuario y contraseña de acceso al servidor, BD (nombre de la base de datos o catálogo). Pulsaremos en «Guardar configuración» y ya la tendremos disponible para el resto de inicios de la aplicación. Pulsando en el botón «Probar conexión» la aplicación comprobará si conecta correctamente con el servidor de base de datos. Si conecta mostrará el mensaje:
Si tenemos facturas dadas de alta, la aplicación las mostrará en el ListView «Lista de facturas»:
A partir de ahora, podremos añadir una nueva factura introduciendo los datos básicos en «Añadir factura» y pulsando en «Añadir»:
La factura se añadirá a la base de datos, la aplicación mostrará un mensaje indicando que se ha añadido una nueva factura y el código (clave primaria) asignado:
Y se mostrará en el ListView «Lista de facturas»:
Desde el ListView «Lista de facturas» podremos modificar una factura ya añadida. Para ello, la seleccionaremos y pulsaremos «Modificar»:
Los datos de la factura se cargarán en el cuadro «Modificar factura». Realizaremos la modificación de los datos que deseemos y pulsaremos en el botón «Modificar»:
La aplicación nos indicará que la factura se ha modificado correctamente:
Y mostrará la factura con los datos actualizados en el ListView «Lista de facturas».
También podremos eliminar una factura, seleccionándola y pulsando en «Eliminar». Nos mostrará una confirmación para eliminar, pulsaremos «Sí»:
Nos indicará que la factura ha sido eliminada correctamente y la quitará del ListView:
Descarga del código fuente completo de la aplicación de ejemplo de gestión de facturas en C Sharp
En el siguiente enlace está disponible, de forma totalmente gratuita, el código fuente completo de la aplicación de ejemplo, desarrollada con Visual Studio .Net Community 2022, en C# y PetaPoco: