Utilidades::DataBaseLogic (C# .Net) – parte 1
Una de las tareas más tediosas y repetitivas cuando se desarrolla un programa de gestión suele ser el acceso a la (o a las) base de datos. Es tediosa porque SQL no es un lenguaje que se compila cuando se genera el binario de una aplicación sino que se compila por el gestor de base de datos en tiempo de ejecución por lo que una coma mal puesta o un no-espacio en blanco puede ocasionar que tu aplicación en un momento dado falle, y es repetitiva porque el 70% de las instrucciones que se lanzan en una aplicación de estas características esta relacionado con el acceso a un base de datos y al final el código de la aplicación se llena de cadenas con comandos SQL e instrucciones para cargar el resultado en variables. Sin contar tareas alternativas como actualizar la estructura de la base de datos y actualizar todos los métodos/funciones afectados o simplemente decidir cambiar de gestor de base datos.
Es por ello que uno de mis primeros objetivos cuando comencé a programar aplicaciones de gestión fue tener una herramienta que me permitiera deshacerme de todos esos problemas y que a su vez tuviera una sintaxis dulce para no llenar el código de instrucciones que no tienen que ver con principio de uso de la aplicación que programo.
La clase en cuestión se llama DataBaseLogic y se encuentra disponible en mi repositorio de utilidades en github (https://github.com/maceoneh/utils). A modo de resumen enumeraré algunas de las características que ofrece:
– Compatibilidad con MySQL y SQLite
– Tipos de datos universales
– Mantenimiento de la base de datos (creación de campos, tablas o índices)
– Especificación de las tablas mediante clases DTO
– Integración con clases DTO
– Creación dinámica de filtros
Empecemos…
En primer lugar es necesario agregar a la solución el proyecto ns.utils.csproj que encontraremos en “\utils\utils\ns.utils.csproj” y después agregar una referencia al proyecto “ns.utils” desde el proyecto desde donde se quiere utilizar la herramienta.

Durante estos tutoriales las pruebas se realizarán con SQLite, motor para que el la herramienta tiene algunas funciones “interesantes”.
Una vez enlazados los proyectos se agrega la directiva “using es.dmoreno.utils.dataaccess.db;”. En primer lugar es necesario crear una instancia de DataBaseLogic, al crearla se debe instanciar con una nueva clase llamada ConnectionParameters la cual sirve para configurar los datos de de conexión tales como el SGDB utilizado o en el caso de SQLite el fichero que contiene la base datos (en caso de no existir lo creará). Es necesario aclarar que la clase DataBaseLogic hereda de la interfaz IDisposable para gestionar la desconexión con la base de datos por lo tanto es recomendable el uso de la instrucción using (como en el ejemplo) o realizar una llamada a Dispose() cuando se ha terminado de usar.
using es.dmoreno.utils.dataaccess.db;
using (var db = new DataBaseLogic(new ConnectionParameters { File = "test.db", Type = DBMSType.SQLite }))
{
}
Creando el esquema de la BD
El siguiente paso es definir el esquema de la base de datos a utilizar, para ello se utilizaran clases DTO donde podremos definir todos esos aspectos. Pongamos por ejemplo que se desea construir una tabla “películas” donde se desea guardar un registro de nuestra colección, en primer lugar se construirá la clase que va a contener dicha información la cual vamos a llamar “Pelicula”.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestDBLogic
{
public class Pelicula
{
public int ID { get; set; }
public string Nombre { get; set; }
public string Descripcion { get; set; }
public int Anyo { get; set; }
}
}
En este sencillo ejemplo se ha definido una clase que contiene 4 propiedades, un ID, el nombre, la descripción y el año de publicación de la película, a continuación se debe asociar con una tabla para ello sobre la definición de clase se incluirá el atributo [Table]. Quedando de la siguiente manera:
[Table(Name = "peliculas")]
internal class Pelicula
{
public int ID { get; set; }
public string Nombre { get; set; }
public string Descripcion { get; set; }
public int Anyo { get; set; }
}
A continuación sobre las propiedades asignaremos el atributo [Field] donde se definirá el nombre del campo, el tipo (integer, string, …), si es primary key, etc.
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace TestDBLogic
{
[Table(Name = "peliculas")]
internal class Pelicula
{
[Field(FieldName = "id", IsAutoincrement = true, IsPrimaryKey = true, Type = ParamType.Int32)]
public int ID { get; set; }
[Field(FieldName = "nombre", Type = ParamType.String)]
public string Nombre { get; set; }
[Field(FieldName = "descripcion", Type = ParamType.String)]
public string Descripcion { get; set; }
[Field(FieldName = "anyo", Type = ParamType.Int32)]
public int Anyo { get; set; }
}
}
Una vez se han definido que atributos de la clase “Pelicula” queremos que se almacenen en la base de datos será posible insertar nuevos registros u obtener un listado pero antes es posible comprobar si existe una tabla con el nombre definido en el atributo [Table] y si no es asi crearla. Para ello se hará uso de la clase dentro de DataBaseLogic llamada Management la cual ofrece el método “createAlterTableAsync<T>()” como se puede ver a continuación.
using es.dmoreno.utils.dataaccess.db;
using TestDBLogic;
using (var db = new DataBaseLogic(new ConnectionParameters { File = "test.db", Type = DBMSType.SQLite }))
{
//Se crea la tabla en caso de no existir
await db.Management.createAlterTableAsync<Pelicula>();
}
Cabe destacar que el uso del método “createAlterTableAsync<T>()” solo es recomendable utilizarlo al inicio del arranque de nuestra aplicación para asegurarnos que no le falta ninguna tabla o campo. Como se puede apreciar ha creado la tabla siguiendo el esquema almacenado en la clase “Pelicula”.

Insertando un registro
Antes he comentado que la utilidad se integra con las clases DTO o modelo, eso significa que estas clases se utilizan como almacén para transferir datos entre la base de datos y la aplicación que programemos, por lo tanto, si queremos agregar un registro a la tabla “peliculas” debemos rellenar un objeto “Pelicula” y enviarlo al objeto “Statement” de DataBaseLogic, en concreto a su método “insertAsync”.
using es.dmoreno.utils.dataaccess.db;
using TestDBLogic;
using (var db = new DataBaseLogic(new ConnectionParameters { File = "test.db", Type = DBMSType.SQLite }))
{
//Se crea la tabla (o se actualiza su estructura) en caso de no existir
await db.Management.createAlterTableAsync<Pelicula>();
//Se rellena un objeto de tipo Pelicula para realizar un insert en la base de datos
var peli = new Pelicula {
Nombre = "New Jack City",
Descripcion = "Ice-T limpiando Nueva York de la escoria Wesley Snipania",
Anyo = 1991
};
//Se procede a insertar el registro
await db.Statement.insertAsync(peli);
}
Como se puede apreciar el registro aparece en la base de datos, no obstante, es importante destacar que el valor del campo “id” no ha sido necesario indicarlo al hacer la inserción ya que al ser del tipo “auto_increment” este tomará el valor automáticamente a la hora de insertarse y se volcará además en el atributo “ID” del objeto utilizado, quedando a disposición del programador sin realizar ninguna acción adicional.

Obteniendo datos
Visto lo anterior ya es posible cargar en un modelo un registro de la base de datos, para ello, se utilizará el atributo de la clase marcado como “Primary Key” que es “ID” para referirnos al registro al que se quiere acceder. Se seguirá utilizando el objeto “Statement” pero en este caso el método “loadAsync<T>(object)” al que le pasamos como argumento el objeto en el que se almacenará los datos de la consulta realizada.
using es.dmoreno.utils.dataaccess.db;
using TestDBLogic;
using (var db = new DataBaseLogic(new ConnectionParameters { File = "test.db", Type = DBMSType.SQLite }))
{
//Se crea la tabla (o se actualiza su estructura) en caso de no existir
await db.Management.createAlterTableAsync<Pelicula>();
//Se rellenan los atributos ID que identifican a la pelicula
var peli_to_load = new Pelicula {
ID = 1
};
//Se realiza la carga
await db.Statement.loadAsync<Pelicula>(peli_to_load);
//Se muestra el resultado
Console.WriteLine(peli_to_load.ID.ToString() + " " + peli_to_load.Nombre + " " + peli_to_load.Anyo.ToString());
Console.ReadLine();
}
El resultado será el siguiente:

Eliminando un registro
Llegados a este punto es posible insertar y obtener un registro, para terminar esta primera parte del manual vamos a ver como se podría eliminar un registro, de la misma forma que se escribe en un modelo los atributos identificadores para cargarlo en este caso se hace para eliminarlo. Para ello, mediante el objeto Statement se llamará al método “deleteAsync(object)”.
using es.dmoreno.utils.dataaccess.db;
using TestDBLogic;
using (var db = new DataBaseLogic(new ConnectionParameters { File = "test.db", Type = DBMSType.SQLite }))
{
//Se crea la tabla (o se actualiza su estructura) en caso de no existir
await db.Management.createAlterTableAsync<Pelicula>();
var peli_to_delete = new Pelicula {
ID = 1
};
await db.Statement.deleteAsync(peli_to_delete);
}
Para la siguiente parte explicaré como realizar sentencias SELECT y todo lo que conlleva (filtros, índices y demas).
Filed under: C#,Programación - @ 30 de junio de 2023 18:39
Etiquetas: c#, csharp, programacion