Inicio > Delphi, DMVCFramework, FireDAC, REST, VCL, WebService > DelphiMVCFramework; Soporte para ActiveRecord

DelphiMVCFramework; Soporte para ActiveRecord

jueves, 3 de diciembre de 2020 Dejar un comentario Ir a comentarios

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.

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.

ActiveRecord

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.

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:

image

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.

5/5 - (2 votos)
  1. alexandre soares pereira lima
    viernes, 22 de enero de 2021 a las 14:59 | #1

    por favor, pode disponibilizar a base de dados TestDb.db

  2. lunes, 25 de enero de 2021 a las 08:31 | #2

    @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.

  3. Josep
    viernes, 5 de marzo de 2021 a las 17:02 | #3

    Felicidades por este completísimo tutorial! Muchísimas Gracias.

  4. lunes, 8 de marzo de 2021 a las 08:37 | #4

    @Josep
    Gracias Josep. Me alegro de que haya sido útil.

  5. Roger Ruiz
    viernes, 14 de mayo de 2021 a las 00:44 | #5

    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

  6. viernes, 14 de mayo de 2021 a las 09:59 | #6

    @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.

  7. Roger
    viernes, 14 de mayo de 2021 a las 10:01 | #7

    @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;

  8. viernes, 14 de mayo de 2021 a las 11:54 | #8

    @Roger
    Gracias por el comentario.
    Un saludo.

  1. Sin trackbacks aún.