DelphiMVCFramework; Soporte para ActiveRecord
Avanzando un poco más en el tema de las últimas entradas, voy a centrarme en esta característica que implementa DMVC. Voy a mostrar la utilización de ActiveRecord para “reimplementar” los métodos de GET, POST, PUT y DELETE que vimos en la última entrada. El resultado final será el mismo, pero cambiaremos la forma de obtener y devolver los datos y de realizar las operaciones sobre la Base de Datos.
A diferencia de la técnica de la tercera entrada, ActiveRecord, sólo podemos utilizarlo si estamos utilizando como componentes de conexión FireDAC.
A continuación os pongo los links de las anteriores:
Entrada 1: DelphiMVCFramework; Framework REST para Delphi
Entrada 2: DelphiMVCFramework; Primeros pasos
Entrada 3: DelphiMVCFramework; Acciones básicas (GET, POST, PUT y DELETE)
Entrada 4: DelphiMVCFramework; Soporte para ActiveRecord
A continuación vamos a ver una introducción al funcionamiento de ActiveRecord, característica que incluye DMVC, como patrón de programación.
Contenido
PATRON ACTIVERECORD
Es un patrón de diseño que permite hacer mapeo objeto-relacional (ORM). Mapea un registro de una tabla de la Base de Datos a un objeto. Soporta operaciones CRUD.
Podemos definir la siguiente relación entre ambos mundos:
Lenguaje de programación OO |
Ítems de la Base de Datos |
Clases | Tablas |
Objetos | Registros de una tabla |
Atributos | Columnas de una tabla |
Algunos links que se pueden consultar sobre este patrón.
- Patrones de Diseño (Active Record vs DAO)
- Active Record en Catalog of Patterns
- Active record en Wikipedia
Para los que ya habéis trabajado con algún Framework de persistencia en Delphi (o en algún otro lenguaje), esto os sonará bastante, porque básicamente es eso. Una implementación básica de la persistencia de registros de la Base de Datos.
GENERAR DE CLASES
Para utilizar ActiveRecord, lo primero que necesitamos es generar una clase que corresponda con nuestra tabla de la Base de Datos. Además esta clase podrá contener la lógica de negocio de nuestras entidades.
En el caso de nuestra tabla de Albums (que vimos en la anterior entrada) y que tenía la siguiente estructura, necesitamos generar una clase como la siguiente:
Código de definición de nuestra tabla TAlbums:
TAlbums = class private FArtistId: integer; FAlbumId: integer; FTitle: string; procedure SetAlbumId(const Value: integer); procedure SetArtistId(const Value: integer); procedure SetTitle(const Value: string); published property AlbumId:integer read FAlbumId write SetAlbumId; property Title:string read FTitle write SetTitle; property ArtistId:integer read FArtistId write SetArtistId; end; |
A esta clase y para que DMVC pueda trabajar con ella utilizando ActiveRecord debemos hacerle algunas pequeñas modificaciones:
- La clase debe derivar de la clase TMVCActiveRecord
- Utilizaremos los atributos MVCTable y MVCTableField para decorar la clase y las variables privadas, para crear una correspondencia entre ellos y los elementos de la Base de Datos.
Además de estos, que son obligatorios, hay otros que podemos utilizar como opcionales. Sería el caso del atributo MVCNameAs en las propiedades, o MVCNameCase en la clase para hacer modificaciones al funcionamiento.
Veremos en el video posterior, que DMVC incluye un ejemplo que nos permite generar de forma fácil el esqueleto de estas clases a partir de las tablas de nuestra Base de Datos. El formato final de esa clase puede ser este:
[MVCNameCase(ncLowerCase)] [MVCTable('artists')] TArtists = class(TMVCActiveRecord) private [MVCTableField('ArtistId', [foPrimaryKey, foAutoGenerated])] fArtistid: Integer {autoincrement}; [MVCTableField('Name')] fName: String; [MVCTableField('Year')] fYear: Integer; [MVCTableField('Soloist')] fSoloist: Boolean; public constructor Create; override; destructor Destroy; override; [MVCNameAs('ArtistId')] property Artistid: Integer {autoincrement} read fArtistid write fArtistid; [MVCNameAs('Name')] property Name: String read fName write fName; [MVCNameAs('Year')] property Year: Integer read fYear write fYear; [MVCNameAs('Soloist')] property Soloist: Boolean read fSoloist write fSoloist; end; |
Una vez tenemos la estructura de nuestras clases, vamos a ver la implementación de los métodos.
METODOS CRUD CON ACTIVERECORD
Si vimos el último día que las operaciones eran bastante simples, vamos a ver que utilizando ActiveRecord aun se simplifican más y siguen siendo muy intuitivas.
Necesitaremos añadir la unit MVCFramework.ActiveRecord al uses de nuestro controlador y para la implementación utilizaremos los siguientes métodos de clase.
METODO GET
Para obtener todos los elementos de una tabla/clase podemos utilizar el método All. Hay otras opciones, pero esta sería la más simple:
lArtistas := TMVCActiveRecord.All{TArtists}; Render{TArtists}(lArtistas); |
(NOTA: sustituir las {} por signos de mayor que y menor que)
Para obtener un único elemento podemos utilizar el método Select o directamente GetByPK si estamos buscando por el campo clave.
METODOS POST Y PUT
En estos casos utilizaremos en Context.Request.BodyAs para obtener los datos que nos llegan desde el cliente y los métodos Insert y Update de la clase TMVCActiveRecord para realizar las inserciones y actualizaciones en Base de Datos.
METODO DELETE
Para este método utilizaremos el método GetByPK que ya hemos visto antes para acceder al elemento que queremos borrar y el método Delete de la clase TMVCActiveRecord.
Al igual que en las entradas anteriores os adjunto un video donde veremos la implementación de estos métodos tal y como hemos descrito y su funcionamiento.
Os adjunto el código del proyecto.
Como siempre los comentarios son bienvenidos.
Hasta la próxima.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
por favor, pode disponibilizar a base de dados TestDb.db
@alexandre soares pereira lima
Hola.
La tienes disponible para descargar al final de esta entrada:
https://neftali.clubdelphi.com/delphimvcframework-primeros-pasos/
Junto con el código del ejemplo.
Felicidades por este completísimo tutorial! Muchísimas Gracias.
@Josep
Gracias Josep. Me alegro de que haya sido útil.
Muy buena explicación, gracias por compartir, aunque a mi no me funcionó lo de Active record, usé Delphi 10.4.2, solo funciona una vez, llamo a un metodo GET me devuelve el JSON pero si haces otra llamada siempre devuelve el error [EMVCException] Cannot create controller, solo funciona la primera vez nada mas, no tengo idea de que hice mal, pero el video me sirvió bastante, saludos
@Roger Ruiz
Gracias por los comentarios Roger.
No se si estás utilizando la misma versión que yo. Siempre puedes trazar el código paso a paso a ver dónde está fallando.
También puedes revisar los ejemplos que vienen con DMVC y comprarlos con el código que expongo.
Es simplemente una prueba de concepto y tal vez me he olvidado algo.
Un saludo.
@Roger Ruiz
El problema esta en esta línea
ActiveRecordConnectionsRegistry.AddDefaultConnection(…);
Al ejecutarse por segunda vez, la conexión sigue activa y da error, pero si espero unos segundos la conexión se pierde y ya puede ser creada de nuevo, lo resolví borrandola con
ActiveRecordConnectionsRegistry.RemoveDefaultConnection;
@Roger
Gracias por el comentario.
Un saludo.