Skip to content

7. Caso de estudio con Firebird 2.1

7.1. Instalación de las herramientas

Las herramientas que hay que instalar son las siguientes:

  • el SGBD: [http://www.firebirdsql.org/en/firebird-2-1-5/];
  • una herramienta de administración: EMS, SQL, Manager para InterBase/Firebird Freeware, [http://www.sqlmanager.net/fr/products/ibfb/manager/download].

En los siguientes ejemplos, el usuario es sysdba con la contraseña masterkey.

Iniciemos Firebird y luego la herramienta [SQL Manager Lite for Firebird], con la que administraremos SGBD.

  • En [1], iniciamos el Firebird SGBD desde el menú Inicio. Aquí, el SGBD no se ha instalado como un servicio de Windows;
  • en [2], el servicio se inicia. Se ha instalado un ícono en la esquina inferior derecha de la pantalla. Al hacer clic derecho sobre él, se puede detener el SGBD.

Ahora iniciamos la herramienta [SQL Manager Lite for Firebird], con la que administraremos el SGBD y el [3].

  • En [4], creamos una nueva base;
  • en [5], aceptamos;
  • en [5], nos conectamos como SYSDBA / masterkey;
  • en [6], se indica la ubicación del archivo que se va a crear. De hecho, la base de datos se creará en un único archivo;
  • en [7], se valida el comando SQL que se ejecutará;
  • en [8], se ha creado la base de datos. Ahora debe guardarse en [EMS Manager]. La información es correcta. Se ejecuta [OK];
  • en [9], nos conectamos a ella;
  • en [10], [EMS Manager] muestra la base de datos, que por el momento está vacía.

Ahora vamos a conectar un proyecto VS 2012 a esta base de datos.

7.2. Creación de la base a partir de las entidades

Comenzamos duplicando la carpeta del proyecto [RdvMedecins-SqlServer-01] en [RdvMedecins-Firebird-01] y [1]:

  • en [2]; en VS 2012, eliminamos el proyecto [RdvMedecins-SqlServer-01] de la solución;
  • en [3], el proyecto se ha eliminado;
  • en [4], se agrega otro. Este se encuentra en la carpeta [RdvMedecins-Firebird-01] que creamos anteriormente;
  • en [5], el proyecto cargado se llama [RdvMedecins-SqlServer-01];
  • en [6], cambiamos su nombre a [RdvMedecins-Firebird-01]
  • en [7], se agrega otro proyecto a la solución. Este se toma de la carpeta [RdvMedecins-SqlServer-01] del proyecto que hemos eliminado de la solución anteriormente;
  • en [8], el proyecto [RdvMedecins-SqlServer-01] se ha reintegrado a la solución.

El proyecto [RdvMedecins-Firebird-01] es idéntico al proyecto [RdvMedecins-SqlServer-01]. Necesitamos realizar algunas modificaciones. En [App.config], vamos a modificar la cadena de conexión y el [DbProviderFactory], que debemos adaptar a cada SGBD.


<!-- cadena de conexión a la base de datos -->
  <connectionStrings>
    <add name="monContexte" connectionString="User=SYSDBA;Password=masterkey;Database=D:\data\istia-1213\c#\dvp\Entity Framework\databases\firebird\RDVMEDECINS-EF.GDB;DataSource=localhost;
Port=3050;Dialect=3;Charset=NONE;Role=;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=50;Packet Size=8192;ServerType=0;" providerName="FirebirdSql.Data.FirebirdClient" />
  </connectionStrings>
  <!-- el proveedor de fábrica -->
  <system.data>
    <DbProviderFactories>
      <add name="Firebird Client Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description=".Net Framework Data Provider for Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient, Version=2.7.7.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c" />
    </DbProviderFactories>
  </system.data>
  • línea 3: el usuario y su contraseña, así como la ruta completa de la base de datos Firebird;
  • líneas 8-10: el archivo DbProviderFactory. La línea 9 hace referencia a un archivo DLL [FirebirdSql.Data.FirebirdClient] que no tenemos. Lo obtenemos con NuGet y [1]:
  • en [2], en el campo de búsqueda escribimos la palabra clave firebird;
  • en [3], se selecciona el paquete [Firebird ADO.NET Data Provider]. Se trata de un conector ADO.NET para Firebird;
  • en [4], la nueva referencia;
  • en [5], en [App.config], hay que indicar la versión correcta de DLL. Esta se encuentra en sus propiedades.

En el archivo [Entites.cs], hay que adaptar el esquema de las tablas que se van a generar:


  [Table("MEDECINS")]
  public class Medecin : Personne
  {...}

  [Table("CLIENTS")]
  public class Client : Personne
  {...}

  [Table("CRENEAUX")]
  public class Creneau
  {...}

  [Table("RVS")]
  public class Rv
  {...}

Aquí, las tablas no tienen esquema.

Configuramos la ejecución del proyecto:

  • en [1], le damos otro nombre al ensamblado que se generará;
  • en [2], así como otro espacio de nombres por defecto;
  • en [3], se designa el programa que se ejecutará.

En esta etapa, no hay errores de compilación. Ejecutemos el programa [CreateDB_01]. Se produce la siguiente excepción:

Exception non gérée : System.Data.MetadataException: Le schéma spécifié n'est pas valide. Erreurs :
(11,6) : erreur 0040: Le type rowversion n'est pas qualifié avec un espace de noms ou un alias. Seuls les types primitifs peuvent être utilisés sans qualification.
(23,6) : erreur 0040: Le type rowversion n'est pas qualifié avec un espace de noms ou un alias. Seuls les types primitifs peuvent être utilisés sans qualification.
(33,6) : erreur 0040: Le type rowversion n'est pas qualifié avec un espace de noms ou un alias. Seuls les types primitifs peuvent être utilisés sans qualification.
(43,6) : erreur 0040: Le type rowversion n'est pas qualifié avec un espace de noms ou un alias. Seuls les types primitifs peuvent être utilisés sans qualification.
   à System.Data.Metadata.Edm.StoreItemCollection.Loader.ThrowOnNonWarningErrors
()
   ...
   à RdvMedecins_01.CreateDB_01.Main(String[] args) dans d:\data\istia-1213\c#\d
vp\Entity Framework\RdvMedecins\RdvMedecins-Oracle-01\CreateDB_01.cs:ligne 15

Recordamos haber tenido el mismo error con MySQL, Oracle y PostgreSQL. Esto está relacionado con el tipo del campo Timestamp de las entidades. Realizamos la misma modificación que con los dos SGBD anteriores. En las entidades, reemplazamos las tres líneas


    [Column("TIMESTAMP")]
    [Timestamp]
    public byte[] Timestamp { get; set; }

por las siguientes:


    [ConcurrencyCheck]
    [Column("VERSIONING")]
    public int? Versioning { get; set; }

Por lo tanto, cambiamos el tipo de la columna de byte[] a int?. En el SGBD, utilizaremos procedimientos almacenados para incrementar este entero en una unidad cada vez que se inserte o modifique una fila.

Realizamos la modificación anterior para las cuatro entidades y luego volvemos a ejecutar la aplicación. Entonces obtenemos el siguiente error:

1
2
3
4
5
Exception non gérée : FirebirdSql.Data.FirebirdClient.FbException: lock time-out on wait transaction object D:\DATA\ISTIA-1213\C#\DVP\ENTITY FRAMEWORK\DATABASES\FIREBIRD\RDVMEDECINS-EF.GDB está en uso ---> FirebirdSql.Data.Common.IscException: tiempo de espera de bloqueo agotado en la transacción en espera
object D:\DATA\ISTIA-1213\C#\DVP\ENTITY FRAMEWORK\DATABASES\FIREBIRD\RDVMEDECINS
-EF.GDB is in use
...
   à RdvMedecins_01.CreateDB_01.Main(String[] args) dans d:\data\istia-1213\c#\dvp\Entity Framework\RdvMedecins\RdvMedecins-Firebird-01\CreateDB_01.cs:línea 15

La línea 1 indica que la base de datos está en uso. Me parece que no era así y no logré resolver este problema.

No importa. Vamos a crear la base de datos [RDVMEDECINS-EF] manualmente con la herramienta [EMS Manager for Firebird]. No describiremos todos los pasos, sino solo los más importantes.

La base de datos Firebird tendrá la siguiente estructura:

Las tablas

  • en [1], ID es una clave primaria con el atributo Autoincrement. Será generada automáticamente por SGBD;

Las diferentes tablas tienen las claves primarias y externas que tenían esas mismas tablas en los ejemplos anteriores. Las claves externas tienen el atributo ON, DELETE y CASCADE.

Los generadores

Al igual que con Oracle y PostgreSQL, hemos creado generadores de números consecutivos. Hay 5: [1].

  • [CLIENTS_ID_GEN] se utilizará para generar la clave primaria de la tabla [CLIENTS];
  • [MEDECINS_ID_GEN] se utilizará para generar la clave primaria de la tabla [MEDECINS];
  • [CRENEAUX_ID_GEN] se utilizará para generar la clave primaria de la tabla [CRENEAUX];
  • [RVS_ID_GEN] se utilizará para generar la clave primaria de la tabla [RVS];
  • [VERSIONS_GEN] se utilizará para generar los valores de las columnas [VERSIONING] de todas las tablas.

Los disparadores

Un disparador es un procedimiento que ejecuta el SGBD antes o después de un evento (inserción, modificación, eliminación) en una tabla. Tenemos 8 [1]:

Veamos el código del disparador DDL que alimenta la columna [ID] de la tabla [CLIENTS]:

1
2
3
4
5
6
7
8
CREATE TRIGGER BI_CLIENTS_ID FOR CLIENTS
ACTIVE BEFORE INSERT
POSITION 0
AS
BEGIN
  IF (NEW.ID IS NULL) THEN
      NEW.ID = GEN_ID(CLIENTS_ID_GEN, 1);
END^
  • línea 2: antes de cada inserción en la tabla [CLIENTS];
  • líneas 6-7: si la columna ID es NULL, entonces se le asigna el siguiente valor del generador de números [CLIENTS_ID_GEN].

Todos los disparadores [ BI_CLIENTS_ID, BI_MEDECINS_ID, BI_CRENEAUX_ID, BI_RVS_ID] están construidos de la misma manera.

Veamos ahora el código DDL del disparador [CLIENTS_VERSION_TRIGGER] que alimenta la columna [VERSIONING] de la tabla [CLIENTS]:

1
2
3
4
5
6
7
CREATE TRIGGER CLIENTS_VERSION_TRIGGER FOR CLIENTS
ACTIVE BEFORE INSERT OR UPDATE
POSITION 1
AS
BEGIN
  NEW."VERSIONING" = GEN_ID(VERSIONS_GEN,1);
END^
  • líneas 1-3: antes de cada operación INSERT o UPDATE en la tabla [CLIENTS];
  • línea 6: la columna ["VERSIONING"] recibe el siguiente valor del generador de números [VERSIONS_GEN]. Este generador alimenta las columnas ["VERSIONING"] de las cuatro tablas.

Los disparadores [MEDECINS_VERSION_TRIGGER, CRENEAUX_VERSION_TRIGGER, RVS_VERSION_TRIGGER] son similares.

El script para generar las tablas de la base de datos Firebird [RDVMEDECINS-EF] se ha colocado en la carpeta [RdvMedecins / databases / Firebird]. El lector podrá cargarlo y ejecutarlo para crear sus tablas.

Una vez hecho esto, se pueden ejecutar los distintos programas del proyecto. Estos arrojan los mismos resultados que con SQL Server, excepto el programa [ModifyDetachedEntities], que falla por la misma razón por la que había fallado con Oracle y MySQL. El problema se resuelve de la misma manera. Basta con copiar el programa [ModifyDetachedEntities] del proyecto [RdvMedecins-Oracle-01] al proyecto [RdvMedecins-Firebird-01].

7.3. Arquitectura multicapa basada en EF 5

Volvemos a nuestro caso de estudio descrito en el párrafo 2.

Comenzaremos por construir la capa de acceso a datos [DAO]. Para ello, duplicamos el proyecto de consola VS 2012 [RdvMedecins-SqlServer-02] en [RdvMedecins-Firebird-02] [1]:

  • en [2], eliminamos el proyecto [RdvMedecins-SqlServer-02];
  • en [3], se agrega un proyecto existente a la solución. Se toma de la carpeta [RdvMedecins-Firebird-02] que se acaba de crear;
  • en [4], el nuevo proyecto lleva el nombre del que se eliminó. Vamos a cambiarle el nombre;
  • en [5], hemos cambiado el nombre del proyecto;
  • en [6], modificamos algunas de sus propiedades, como en este caso el nombre del ensamblado;
  • en [7], se elimina la carpeta [Models] para sustituirla por la carpeta [Models] del proyecto [RdvMedecins-Firebird-01]. De hecho, ambos proyectos comparten las mismas plantillas.
  • en [8], las referencias actuales del proyecto;
  • en [9], se ha agregado el conector ADO.NET de Firebird con la herramienta NuGet.

En el archivo [App.config], se reemplaza la información de la base de datos SQL Server por la de la base de datos Firebird. Esta información se encuentra en el archivo [App.config] del proyecto [RdvMedecins-Firebird-01]:


<!-- cadena de conexión a la base de datos -->
  <connectionStrings>
    <add name="monContexte" connectionString="User=SYSDBA;Password=masterkey;Database=D:\data\istia-1213\c#\dvp\Entity Framework\databases\firebird\RDVMEDECINS-EF.GDB;DataSource=localhost;
Port=3050;Dialect=3;Charset=NONE;Role=;Connection lifetime=15;Pooling=true;MinPoolSize=0;MaxPoolSize=50;Packet Size=8192;ServerType=0;" providerName="FirebirdSql.Data.FirebirdClient" />
  </connectionStrings>
  <!-- el proveedor de fábrica -->
  <system.data>
    <DbProviderFactories>
      <add name="Firebird Client Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description=".Net Framework Data Provider for Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient, Version=2.7.7.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c" />
    </DbProviderFactories>
  </system.data>

Los objetos gestionados por Spring también cambian. Actualmente tenemos:


  <!-- configuración de Spring -->
  <spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>
    <objects xmlns="http://www.springframework.net">
      <object id="rdvmedecinsDao" type="RdvMedecins.Dao.Dao,RdvMedecins-SqlServer-02" />
    </objects>
</spring>

La línea 7 hace referencia al ensamblado del proyecto [RdvMedecins-SqlServer-02]. El ensamblado ahora es [RdvMedecins-Firebird-02].

Una vez hecho esto, estamos listos para ejecutar la prueba de la capa [DAO]. Antes hay que asegurarse de llenar la base de datos (programa [Fill] del proyecto [RdvMedecins-Firebird-01]). La prueba se ejecuta con éxito.

Creamos el DLL del proyecto tal como se hizo para el proyecto [RdvMedecins-SqlServer-02] y reunimos eltodos los archivos DLL del proyecto en una carpeta [lib] creada dentro de [RdvMedecins-Firebird-02]. Estas serán las referencias del proyecto web [RdvMedecins-Firebird-03] que se desarrollará a continuación.

  

Ahora estamos listos para construir la capa [ASP.NET] de nuestra aplicación:

Partiremos del proyecto [RdvMedecins-SqlServer-03]. Duplicamos la carpeta de este proyecto en [RdvMedecins-Firebird-03] y [1]:

  • en [2], con VS 2012 Express para la web, abrimos la solución de la carpeta [RdvMedecins-Firebird-03];
  • en [3], cambiamos tanto el nombre de la solución como el del proyecto;
  • en [4], las referencias actuales del proyecto;
  • en [5], las eliminamos;
  • a [6], para reemplazarlas por referencias a DLL, que acabamos de guardar en una carpeta [lib] del proyecto [RdvMedecins-Firebird-02].

Ahora solo nos queda modificar el archivo [Web.config]. Reemplazamos su contenido actual por el contenido del archivo [App.config] del proyecto [RdvMedecins-Firebird-02]. Una vez hecho esto, ejecutamos el proyecto web. Funciona. No nos olvidemos de llenar la base de datos antes de ejecutar la aplicación web.