PROGRAMACIÓN DE
APLICACIONES DELPHI CON
ACCESO A BASES DE DATOS
por Francisco Charte
para Jorge Villalobos
© 2016 | Danysoft
DERECHOS RESERVADOS
El contenido de esta publicación tiene todos los derechos reservados, por lo que no se puede reproducir, transcribir,
transmitir, almacenar en un sistema de recuperación o traducir a otro idioma de ninguna forma o por ningún medio
mecánico, manual, electrónico, magnético, químico, o de otro modo. La persecución de una reproducción no
autorizada tiene como consecuencia la cárcel y/o multas.
LIMITACIÓN DE LA RESPONSABILIDAD
Tanto el autor como en Danysoft hemos revisado el texto para evitar cualquier tipo de error, pero no podemos prometerle
que el libro esté siempre libre de errores. Por ello le rogamos nos remita por e-mail sus comentarios sobre el libro
a attcliente@[Link]
DESCUENTOS ESPECIALES
Recuerde que Danysoft ofrece descuentos especiales a centros de formación y en adquisiciones por volumen. Para más
detalles, consulte con Danysoft.
MARCAS REGISTRADAS
Todos los productos y marcas se mencionan únicamente con fines de identificación y están registrados por sus
respectivas compañı́as.
Autor: Francisco Charte
Publicado por Danysoft
Avda. de la Industria, 4 Edif. 1
28108 Alcobendas, Madrid. España.
902 123146 — [Link]
para Jorge Villalobos
IMPRESO EN ESPAÑA
Depósito Legal | M-1195-2016
© Danysoft | Madrid | 2016 | versión en castellano.
A mi familia
CONTENIDOS EN BREVE
Introducción 39
PARTE I ACCESO A DATOS LOCALES
Introducción a FireDAC 61
Herramientas BDD en Delphi 89
Interfaces de usuario con conexión a datos 123
InterBase embebido 155
Bases de datos de escritorio 181
Bases de datos en memoria 209
Bases de datos y Unicode 229
PARTE II APLICACIONES CLIENTE/SERVIDOR
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
8 CONTENIDOS EN BREVE
Introducción al desarrollo cliente/servidor 263
Transacciones, bloqueos y notificación de cambios 311
Trabajar sin conexión al RDBMS 333
Interbase 359
PARTE III APLICACIONES DISTRIBUIDAS
Introducción al desarrollo distribuido con Delphi 375
Servicios DataSnap 393
Servicios REST 425
Introducción a EMS 469
PARTE IV APÉNDICES
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Contenidos
Lista de figuras 23
Agradecimientos 37
Introducción 39
1.1 Aplicaciones móviles 40
1.2 Aplicaciones Windows/OS X 41
1.3 Aplicaciones web 42
1.4 Servicios de acceso a bases de datos y Delphi 43
1.4.1 BDE 44
1.4.2 IBX 47
1.4.3 dbGo 48
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
10 CONTENIDOS
1.4.4 dbExpress 50
1.4.5 DataSnap 52
1.4.6 FireDAC 53
1.5 Sobre este libro 55
1.5.1 Estructura 56
1.5.2 Notación 57
PARTE I ACCESO A DATOS LOCALES
Introducción a FireDAC 61
2.1 Hola FireDAC 62
2.1.1 Inicio del proyecto 62
2.1.2 Adición de un módulo de datos 64
2.1.3 Configuración de la conexión 65
2.1.4 Creación de una tabla 67
2.1.5 Introducción de datos 69
2.1.6 Otros componentes a añadir al módulo de datos 71
2.1.7 Diseño de la interfaz de usuario 72
2.1.8 Enlace entre interfaz y datos 73
2.1.9 Prueba de la aplicación 75
2.2 Bases de datos locales y FireDAC 76
2.2.1 InterBase Lite e InterBase ToGo 77
2.2.2 SQLite 78
2.2.3 Microsoft Access 79
2.2.4 Archivos de datos en otros formatos 80
2.3 Estructura de una aplicación que usa FireDAC 81
2.3.1 Controladores FireDAC 83
2.3.2 Conjuntos de datos 85
2.3.3 Elementos de interfaz 86
2.3.4 Otros componentes FireDAC 87
2.4 Resumen 88
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONTENIDOS 11
Herramientas del Entorno de Delphi para BDD 89
3.1 Módulos de datos 90
3.2 Data Explorer 91
3.2.1 Definición de conexiones 91
3.2.2 Exploración de datos 94
3.2.3 Inserción de componentes de conexión 95
3.3 FireDAC Explorer 97
3.3.1 Archivos de definición de conexiones locales a un
proyecto 99
3.3.2 Estructura de un archivo de definición de conexiones
FireDAC 100
3.4 FireDAC Monitor 101
3.4.1 Componentes de supervisión FireDAC 101
3.4.2 La interfaz de FireDAC Monitor 103
3.5 Herramientas asociadas a componentes FireDAC 104
3.5.1 El Editor de campos 104
3.5.2 El Editor de consultas 108
3.6 El asistente de Live Bindings 110
3.7 En la práctica 111
3.7.1 Conexión y selección de datos 112
3.7.2 Configuración para la inspección de actividad 113
3.7.3 Edición de la consulta de selección de datos 113
3.7.4 Adición de un campo calculado 114
3.7.5 Diseño de la interfaz de usuario 115
3.7.6 Conexión entre interfaz y datos 116
3.7.7 Código de activación y filtrado 118
3.7.8 Probando la aplicación 118
3.7.9 Preparar la aplicación para su despliegue 119
3.8 Resumen 121
Interfaces de usuario con conexión a datos 123
4.1 VCL versus FMX 124
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
12 CONTENIDOS
4.1.1 Plataformas objetivo 124
4.1.2 Hardware y software de base 126
4.1.3 Compatibilidad hacia atrás 128
4.2 FireDAC y aplicaciones VCL 129
4.2.1 Módulo de datos y componentes FireDAC 130
4.2.2 Interfaz de usuario 132
4.3 Componentes VCL con conexión a datos 133
4.4 LiveBindings 135
4.4.1 Componentes LiveBindings esenciales 136
4.4.2 Adición y enlace de controles 140
4.5 Diseño de una interfaz con controles simples y navegación 141
4.5.1 Origen de los datos 142
4.5.2 Diseño de la interfaz de usuario 143
4.5.3 Controles de navegación 144
4.6 Otras configuraciones de datos 145
4.6.1 Relaciones maestro/detalle 146
4.6.2 Campos de búsqueda 147
4.6.3 En la práctica 148
4.7 Resumen 153
Aplicaciones con InterBase embebido 155
5.1 InterBase ToGo 156
5.1.1 Licencias ToGo e IBLite 157
5.2 Herramientas InterBase para desarrollo 157
5.2.1 InterBase Manager 158
5.2.2 La consola de InterBase 159
5.3 InterBase y FireDAC 161
5.4 Caso práctico 162
5.4.1 Configuración de la conexión 163
5.4.2 Selección de datos 164
5.4.3 Diseño de la interfaz 165
5.4.4 Enlace con los datos 167
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONTENIDOS 13
5.4.5 Gestión de los eventos 169
5.4.6 Comprobación de la aplicación 170
5.5 Configuración de despliegue 170
5.5.1 Ruta de la base de datos 171
5.5.2 Redistribución de IBLite y su licencia 173
5.5.3 Distribución de la base de datos 174
5.5.4 Configuración de permisos 174
5.5.5 Comprobación de la aplicación 175
5.6 Resumen 179
Delphi y Bases de Datos de Escritorio 181
6.1 Acceso a datos en archivos de Microsoft Excel 182
6.1.1 FireDAC y Excel 182
6.1.2 Configuración de FireDAC para usar un controlador
ODBC 183
6.1.3 Consultas sobre un libro Excel 184
6.1.4 Supuesto práctico 185
6.1.5 Configuración de la conexión por ODBC 187
6.1.6 Consulta de recuperación de datos 188
6.1.7 Diseño de la interfaz de usuario 189
6.1.8 Apertura de la conexión 191
6.1.9 Exportación de los datos 192
6.2 Uso de datos almacenados en archivos de texto 195
6.2.1 Lectura de archivos CSV con FireDAC 195
6.2.2 Procesamiento local de consultas SQL 197
6.2.3 Consultas sobre archivos CSV 199
6.2.4 Componentes de conexión y procesamiento de consultas 199
6.2.5 Lectura de los datos CSV 200
6.2.6 Diseño de la interfaz 204
6.3 Resumen 206
Bases de datos en memoria con FireDAC 209
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
14 CONTENIDOS
7.1 El motor local de SQL de FireDAC 210
7.2 Conjuntos de datos en memoria 211
7.3 Definición de estructuras de datos en memoria 212
7.3.1 En la fase de diseño 213
7.3.2 Durante la ejecución 216
7.4 Caso práctico 219
7.4.1 Configuración de los componentes de datos 220
7.4.2 Diseño de la interfaz de usuario 222
7.5 Exportación de los datos 225
7.5.1 El componente TFDSQLiteBackup 226
7.5.2 En la práctica 227
7.6 Resumen 228
Bases de datos y Unicode 229
8.1 Introducción a Unicode 230
8.1.1 Estándares de codificación: ASCII 230
8.1.2 Unicode y las codificaciones UTF-N 232
8.1.3 Unicode y cabecera BOM 235
8.2 Soporte Unicode en Delphi 236
8.2.1 Tipos de cadenas y caracteres 238
8.2.2 Conversión entre codificaciones 241
8.2.3 Lectura/Escritura de archivos Unicode 245
8.3 Bases de datos y Unicode 252
8.3.1 Configuración Unicode en FireDAC 252
8.3.2 Aspectos especı́ficos de los RDBMS 257
8.4 Resumen 259
PARTE II APLICACIONES CLIENTE/SERVIDOR
Introducción al desarrollo cliente/servidor 263
9.1 Conexión con el servidor de datos 264
9.1.1 Ruta y nombre de la base de datos 264
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONTENIDOS 15
9.1.2 Autenticación de acceso 265
9.1.3 Reutilización de conexiones 267
9.1.4 Gestión de las conexiones durante la ejecución 270
9.2 Obtención de datos 272
9.2.1 Selección de columnas 273
9.2.2 Filtrado de filas 274
9.2.3 Paginación de resultados 275
9.3 Edición de datos 281
9.3.1 Cómo actualiza FireDAC los datos 282
9.3.2 Generación de las sentencias para actualizar datos 284
9.4 Procesamiento de datos en el servidor 296
9.4.1 Agrupación y agregado de datos 296
9.4.2 Otros cálculos sobre los datos 298
9.4.3 Actualización de datos por lotes 301
9.5 Ejecución de scripts SQL 302
9.5.1 Vı́as para aportar el código SQL a ejecutar 303
9.5.2 Edición y prueba del guión en la fase de diseño 304
9.5.3 Asociar un cuadro de diálogo especı́fico 306
9.5.4 En la práctica 306
9.6 Resumen 309
Transacciones, bloqueos y notificación de cambios 311
10.1 Introducción al uso de transacciones 312
10.1.1 Propiedades de una transacción 312
10.1.2 Operaciones de control de una transacción 313
10.2 Transacciones de base de datos vs transacciones FireDAC 314
10.3 Control de transacciones en FireDAC 315
10.3.1 Transacciones automáticas 315
10.3.2 Transacciones manuales 317
10.3.3 Configuración de las transacciones 318
10.3.4 Transacciones anidadas 319
10.3.5 Conflictos de concurrencia 320
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
16 CONTENIDOS
10.4 Notificación de cambios 323
10.4.1 Configuración de la solicitud 324
10.4.2 Registro con el servidor y eventos 325
10.4.3 Actualización automática de datos 326
10.4.4 Transacciones y notificaciones en la práctica 327
10.5 Resumen 331
Trabajar sin conexión al RDBMS 333
11.1 El modo desconectado de FireDAC 334
11.1.1 Conectar/Desconectar de la base de datos 335
11.1.2 Reconexión automática 336
11.2 Actualizaciones por lotes 340
11.2.1 Activación de la actualización por lotes 340
11.2.2 Deshacer cambios hechos a los datos 341
11.2.3 Envı́o de los cambios pendientes 342
11.2.4 Gestión de conflictos 349
11.2.5 Actualización por lotes centralizada 355
11.3 Resumen 357
Interbase 359
12.1 Versiones de InterBase 360
12.2 Configuración del cliente 361
12.3 Configuración de la conexión 363
12.3.1 Protocolo, servidor y puerto 364
12.3.2 Autenticación 365
12.3.3 Identificación de la base de datos 366
12.3.4 Otros parámetros 367
12.4 Componentes FireDAC Services 368
12.4.1 Metodologı́a general de uso 370
12.4.2 Funcionalidad de los componentes de servicio 371
12.5 Resumen 372
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONTENIDOS 17
PARTE III APLICACIONES DISTRIBUIDAS
Introducción al desarrollo distribuido con Delphi 375
13.1 Estructura de una aplicación distribuida 376
13.1.1 Servidor de datos 377
13.1.2 Servidor de aplicaciones 378
13.1.3 Interfaz de usuario 378
13.2 Comunicación entre interfaz y servidor de aplicaciones 379
13.3 Introducción a REST 380
13.3.1 Composición de las rutas de acceso 381
13.3.2 Verbos HTTP y operaciones 382
13.4 Introducción a JSON 383
13.4.1 Sintaxis de JSON 383
13.4.2 Trabajar con JSON en Delphi 386
13.5 Resumen 392
Servicios DataSnap 393
14.1 Aspectos fundamentales de DataSnap 394
14.1.1 Aplicación contenedora 394
14.1.2 Elementos del servidor DataSnap 395
14.1.3 Componentes en el servidor 396
14.2 Un servicio simple 398
14.2.1 Implementación del servicio 402
14.2.2 Acceso al servicio desde el IDE 404
14.2.3 Un consumidor simple 406
14.2.4 Control del estado del servidor 413
14.3 DataSnap y conjuntos de datos 415
14.3.1 Aspectos especı́ficos en el servidor 416
14.3.2 Devolución de un conjunto de datos 418
14.3.3 Recepción de los datos en el cliente 419
14.3.4 Devolución de los cambios 422
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
18 CONTENIDOS
14.4 Resumen 423
Servicios REST 425
15.1 El asistente DataSnap REST 426
15.1.1 Módulo de clases del servidor 428
15.1.2 Módulo web 429
15.1.3 Módulo de interfaz 435
15.2 Un servicio REST simple 435
15.2.1 Comprobación del servidor desde el navegador 438
15.3 Acceso a servicios REST desde Delphi 440
15.3.1 Componentes de un cliente REST 440
15.3.2 Consumo del servicio simple desde un cliente Delphi 442
15.3.3 El depurador REST 445
15.4 Acceso a servicios DataSnap con jQuery 448
15.4.1 Módulos proxy 448
15.4.2 Una interfaz jQuery Mobile 450
15.4.3 Invocaciones mediante AJAX 453
15.4.4 Integración del cliente JavaScript en el servidor 455
15.5 DataSnap REST y conjuntos de datos 458
15.5.1 FireDAC JSON Reflection 459
15.5.2 Desarrollo del servidor 460
15.5.3 Desarrollo del cliente 463
15.6 Resumen 468
Introducción a EMS 469
16.1 Caracterı́sticas de EMS 470
16.1.1 Funcionalidad de EMS 470
16.1.2 Herramientas de desarrollo 471
16.1.3 Componentes para aplicaciones 472
16.2 El servidor EMS 474
16.2.1 Configuración del servidor EMS 474
16.2.2 Consola de control del servidor 476
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONTENIDOS 19
16.2.3 La consola de desarrollo 476
16.3 Servicios ofrecidos por EMS 478
16.3.1 Gestión de grupos 479
16.3.2 Gestión de usuarios 481
16.3.3 Otros servicios 484
16.4 Componentes Delphi para operar con EMS 484
16.5 Desarrollo de paquetes EMS 489
16.5.1 El asistente para paquetes EMS 490
16.5.2 Atributos y registro de las clases de recurso 490
16.5.3 Versión EMS del servidor de números aleatorios 492
16.6 Resumen 495
PARTE IV APÉNDICES
A El entorno de Delphi 499
A.1 El IDE del Delphi 500
A.1.1 Cómo cambiar la distribución de los paneles del IDE 502
A.1.2 La herramienta IDE Insight 505
A.2 Gestión de proyectos 506
A.2.1 Proyectos y plantillas 506
A.2.2 El Gestor de proyectos 509
A.3 Vistas de diseño 511
A.3.1 Cambiar la vista activa 512
A.3.2 Orientación y máscara 513
A.3.3 Vista maestra y vistas especı́ficas 514
A.3.4 Visualización preliminar de la interfaz 515
A.4 Trabajar con componentes 517
A.4.1 Adición de nuevos componentes 518
A.4.2 Manipulación de componentes 520
A.4.3 Edición de propiedades 521
A.5 Edición de código 524
A.5.1 Enlace entre eventos y métodos 525
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
20 CONTENIDOS
A.5.2 Asistencia a la edición de código 526
A.6 Gestión de plataformas 530
A.7 Generación del proyecto 532
A.7.1 Compilación 532
A.7.2 Ejecución y depuración 533
A.8 Resumen 541
B El lenguaje Delphi 543
B.1 Sintaxis básica 544
B.1.1 Módulos de código Delphi 545
B.1.2 Estructura del módulo de programa 546
B.1.3 Estructura de un módulo de código estándar 548
B.1.4 Referencias a módulos 549
B.1.5 Comentarios 552
B.2 Tipos de datos fundamentales 553
B.2.1 Números enteros y de coma flotante 554
B.2.2 Caracteres y cadenas de caracteres 556
B.2.3 Otros tipos de datos básicos 557
B.2.4 Notación para literales e identificadores 558
B.2.5 Enumeraciones 560
B.2.6 Subrangos 563
B.2.7 Vectores y matrices (Arrays) 565
B.2.8 Registros 570
B.2.9 Conjuntos 574
B.3 Expresiones 576
B.3.1 Expresiones aritméticas, relacionales y lógicas 576
B.3.2 Expresiones con conjuntos 578
B.3.3 Expresiones con punteros 578
B.3.4 Otros tipos de expresiones 578
B.4 Sentencias 580
B.4.1 Estructuras condicionales 580
B.4.2 Estructuras iterativas 582
B.4.3 Procedimientos y funciones 584
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONTENIDOS 21
B.4.4 Control estructurado de excepciones 589
B.4.5 Otras sentencias 591
B.5 Clases y sus miembros 592
B.5.1 Cómo definir una nueva clase 593
B.5.2 Visibilidad de los miembros de una clase 595
B.5.3 Construcción de objetos 596
B.5.4 La clase TCollectible 598
B.5.5 La clase TComputer 608
B.6 Miembros de clase y el objeto self 612
B.6.1 La clase TCollection 613
B.7 Métodos anónimos 617
B.7.1 Escenario de uso de un método anónimo 618
B.7.2 Definición de tipo de un método anónimo 619
B.7.3 Cómo pasar métodos anónimos como parámetros 620
B.8 Tipos genéricos 621
B.8.1 Cómo definir un tipo genérico 622
B.8.2 Instanciación y uso de tipos genéricos 624
B.9 Ayudas a la escritura de código 626
B.9.1 Plantillas de código 626
B.9.2 Dar formato al código 629
B.9.3 Navegar por el código 629
B.9.4 Refactorización del código 630
B.9.5 Gestión de versiones del código 631
B.10 Resumen 632
C Integración de Delphi con Git 633
C.1 Instalación de Git 635
C.1.1 Uso de Git en Windows 636
C.1.2 Configuración de Git 637
C.2 Integración de Git con Delphi 639
C.3 Operaciones comunes al trabajar con Git y Delphi 640
C.3.1 Clonación de un repositorio Git 640
C.3.2 Inicializar un repositorio local 644
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
22 CONTENIDOS
C.3.3 Comprobar el estado de nuestra versión local 646
C.3.4 Confirmar y revertir cambios en un módulo 650
C.3.5 Enviar/Recibir cambios de un repositorio remoto 651
C.4 Configurar un repositorio Git 653
C.5 Resumen 655
D Migración de aplicaciones BDE a FireDac 657
D.1 Instalar BDE en XE7 y versiones posteriores 658
D.2 Diferencias entre BDE y FireDAC 662
D.2.1 Orı́genes de datos 662
D.2.2 API de programación 663
D.2.3 Componentes 663
D.2.4 Definición de conexiones 665
D.3 Herramientas de conversión 666
D.4 Resumen 668
Índice alfabético 669
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LISTA DE FIGURAS
1.1 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN BDE. 45
1.2 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN IBX. 48
1.3 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN DB G O . 49
1.4 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN DB E XPRESS . 51
1.5 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN DATA S NAP. 52
1.6 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN F IRE DAC. 54
2.1 I NICIAMOS UN NUEVO PROYECTO DE APLICACI ÓN MULTI - DISPOSITIVO . 63
2.2 A ÑADIMOS UN M ÓDULO DE DATOS AL PROYECTO . 64
2.3 S ELECCIONAMOS EL TIPO DE BASE DE DATOS . 65
2.4 A BRIMOS EL EDITOR DE PAR ÁMETROS DE CONEXI ÓN . 66
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
24 LISTA DE FIGURAS
2.5 I NTRODUCIMOS LA SENTENCIA SQL PARA CREAR LA TABLA . 68
2.6 A BRIMOS LA TABLA DESDE EL E XPLORADOR DE DATOS . 70
2.7 I NTRODUCIMOS ALGUNOS DATOS EN LA TABLA . 70
2.8 C OMPONENTES INTRODUCIDOS EN EL M ÓDULO DE DATOS . 71
2.9 C ONFIGURAMOS EL TL IST V IEW. 72
2.10 AGREGAMOS AL FORMULARIO UNA REFERENCIA AL M ÓDULO DE
DATOS . 73
2.11 E NLAZAMOS COLUMNAS DE LA TABLA CON PROPIEDADES DEL
CONTROL . 74
2.12 C ONFIGURACI ÓN FINAL DE LOS ENLACES . 75
2.13 L A APLICACI ÓN EN FUNCIONAMIENTO . 76
2.14 E STRUCTURA DE UNA APLICACI ÓN D ELPHI QUE USA F IRE DAC
PARA ACCEDER A UNA BASE DE DATOS LOCAL . 82
2.15 C OMPONENTES PARA ENLAZAR LOS CONTROLADORES EN EL
PROYECTO . 84
2.16 C OMPONENTES F IRE DAC ASOCIADOS A ELEMENTOS DE LA
INTERFAZ DE USUARIO . 86
2.17 S ELECCI ÓN DEL PROVEEDOR DE INTERFAZ DE USUARIO . 87
3.1 AGREGAMOS UNA NUEVA CONEXI ÓN ASOCIADA AL CONTROLADOR
DE I NTER BASE . 92
3.2 O PCIONES DE CONFIGURACI ÓN DE LA CONEXI ÓN . 93
3.3 E XPLORACI ÓN DE LA ESTRUCTURA DE UNA BASE DE DATOS . 94
3.4 C OMPONENTES AGREGADOS MEDIANTE ARRASTRAR Y SOLTAR . 96
3.5 F IRE DAC E XPLORER . 97
3.6 E S POSIBLE CREAR GRUPOS , ORDENAR Y FILTRAR LOS DATOS . 98
3.7 C ONFIGURACI ÓN DE SUPERVISI ÓN EN EL COMPONENTE
TFDC O N N E C T I O N . 102
3.8 I NTERFAZ DE USUARIO DEL PROGRAMA F IRE DAC M ONITOR . 103
3.9 O PCIONES ASOCIADAS AL COMPONENTE TFDQ U E R Y . 104
3.10 E L E DITOR DE CAMPOS Y SU MEN Ú CONTEXTUAL . 105
3.11 P ROPIEDADES DE UN OBJETO TF I E L D EN EL I NSPECTOR DE OBJETOS . 106
3.12 D EFINICI ÓN DEL NUEVO CAMPO AGREGADO AL CONJUNTO DE DATOS . 107
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LISTA DE FIGURAS 25
3.13 E L E DITOR DE CONSULTAS NOS PERMITE PROBAR LAS SENTENCIAS
SQL. 108
3.14 C ONFIGURACI ÓN DE PAR ÁMETROS USADOS EN LA CONSULTA . 110
3.15 A SISTENTE PARA L IVE B INDINGS . 111
3.16 F ORMULARIO FINALIZADA LA INSERCI ÓN DE COMPONENTES . 116
3.17 E L PROGRAMA EN FUNCIONAMIENTO . 119
3.18 I NSPECCIONAMOS LA OPERACI ÓN DE ACTUALIZACI ÓN . 120
4.1 VCL SOLO EST Á DISPONIBLE PARA W IN 32 Y W IN 64. 125
4.2 FMX TAMBI ÉN EST Á DISPONIBLE PARA OS X, I OS Y A NDROID . 126
4.3 P ROPIEDADES PARA APLICAR TRANSFORMACIONES EN FMX. 127
4.4 C OMPONENTES ESPEC ÍFICOS PARA W INDOWS EN LA VCL. 128
4.5 C REAMOS UN NUEVO PROYECTO BASADO EN LA VCL. 130
4.6 AGREGAMOS AL M ÓDULO DE DATOS LOS COMPONENTES F IRE DAC. 131
4.7 I NTERFAZ DE USUARIO CON CUADR ÍCULA Y TC H E C K B O X . 132
4.8 C ONTROLES VCL CON CAPACIDAD PARA CONECTARSE A DATOS . 134
4.9 C OMPONENTES FUNDAMENTALES DE L IVE B INDINGS . 136
4.10 C ONFIGURACI ÓN DE UN TB I N D D A T A S O U R C E DB. 138
4.11 D ISE ÑADOR ASOCIADO AL COMPONENTE TB I N D I N G S L I S T . 139
4.12 L ISTA DE CLASES DE ENLACES LiveBindings. 139
4.13 I NSERTAR Y ENLAZAR UN NUEVO CONTROL A UN CAMPO DE DATOS . 141
4.14 P ODEMOS SELECCIONAR LAS COLUMNAS A INCLUIR . 143
4.15 D ISPOSICI ÓN DE LOS CONTROLES Y ENLACES AL ORIGEN DE DATOS . 144
4.16 L A APLICACI ÓN VCL EN FUNCIONAMIENTO . 145
4.17 E STABLECEMOS EL V ÍNCULO ENTRE TABLA MAESTRA Y DE DETALLE . 149
4.18 S ELECCI ÓN DE LOS CAMPOS PARA EL V ÍNCULO MAESTRO / DETALLE . 150
4.19 C ONFIGURACI ÓN DEL CAMPO DE B ÚSQUEDA . 151
4.20 E NLACES ENTRE COLUMNAS DE DATOS Y CONTROLES DE INTERFAZ . 152
4.21 E L PROGRAMA CON LA INTERFAZ MAESTRO / DETALLE EN
FUNCIONAMIENTO . 153
5.1 I NTERFAZ DEL I NTER BASE M ANAGER . 158
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
26 LISTA DE FIGURAS
5.2 C ONSOLA DE I NTER BASE . 160
5.3 C ONFIGURACI ÓN DE CONEXI ÓN A LA BASE DE DATOS . 163
5.4 C OMPONENTES F IRE DAC AGREGADOS AL M ÓDULO DE DATOS . 166
5.5 E STRUCTURA DE LA INTERFAZ DE USUARIO . 167
5.6 C ONFIGURACI ÓN DE ENLACE A DATOS DEL FORMULARIO . 168
5.7 E L PROGRAMA EN FUNCIONAMIENTO EN W INDOWS . 171
5.8 C OMPONENTES REDISTRIBUIBLES A AGREGAR AL PROYECTO . 173
5.9 I NCLUIMOS LA PROPIA BASE DE DATOS ENTRE LOS ARCHIVOS A
DISTRIBUIR . 174
5.10 C ONFIGURACI ÓN DE PERMISOS DE LA APLICACI ÓN . 175
5.11 E LEGIMOS LA PLATAFORMA EN QUE SE DESPLEGAR Á EL PROYECTO . 176
5.12 PAS ERVER M ANAGER . 176
5.13 L A APLICACI ÓN FUNCIONANDO EN EL EMULADOR DE I OS. 177
5.14 E RROR AL INTENTAR CONECTAR . 178
5.15 C OMPROBAMOS LOS ARCHIVOS EN LA CARPETA DE DESPLIEGUE . 178
6.1 C ONTENIDO DE LA HOJA E XCEL . 186
6.2 C ONFIGURACI ÓN DE LA CONEXI ÓN AL ARCHIVO E XCEL . 187
6.3 C ONSULTA PARA OBTENER LOS DATOS DE LA HOJA . 189
6.4 E NLACE ENTRE LA CUADR ÍCULA Y LOS DATOS . 190
6.5 C ONFIGURACI ÓN DE LAS COLUMNAS DEL TG R I D . 190
6.6 L A CUADR ÍCULA MOSTRANDO LOS DATOS DE LA HOJA E XCEL . 191
6.7 L A APLICACI ÓN EN FUNCIONAMIENTO . 193
6.8 L A HOJA DE DATOS AGREGADA POR LA APLICACI ÓN D ELPHI AL
LIBRO E XCEL . 194
6.9 C OMPONENTES F IRE DAC PARA TRANSFERIR DATOS ENTRE ORIGEN
Y DESTINO . 196
6.10 P ROCESO DE TRANSFERENCIA DE DATOS CON TB A T C H M O V E . 197
6.11 C OMPONENTES A INTRODUCIR EN EL M ÓDULO DE DATOS . 201
6.12 C ONFIGURACI ÓN DEL TFDB A T C H M O V E . 201
6.13 C ONFIGURACI ÓN DEL COMPONENTE TFDB A T C H M O V E T E X T R E A D E R . 202
6.14 A SPECTO DE LA INTERFAZ EN EL DISE ÑADOR DE FORMULARIOS . 205
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LISTA DE FIGURAS 27
6.15 E L PROGRAMA MOSTRANDO DATOS DE DOS ARCHIVOS CSV. 205
7.1 O PCIONES EN EL MEN Ú CONTEXTUAL DE UN TFDM E M T A B L E . 211
7.2 D EFINICI ÓN DE COLUMNAS DE UNA TABLA CON EL E DITOR DE
CAMPOS . 213
7.3 O PCIONES EN EL TFDM E M T A B L E TRAS HABER GENERADO EL
CONJUNTO DE DATOS . 214
7.4 E STRUCTURA DE LA INTERFAZ DE USUARIO . 223
7.5 E NLACE DE LAS CUADR ÍCULAS CON LOS COMPONENTES DE DATOS . 224
7.6 L A APLICACI ÓN MOSTRANDO LA BASE DE DATOS EN MEMORIA . 225
7.7 EXAMINAMOS LOS DATOS EXPORTADOS CON TFDSQLI T EBA C K U P . 228
8.1 C ONJUNTO DE CARACTERES ASCII DE 7 BITS . 231
8.2 C ONJUNTO DE CARACTERES ASCII EXTENDIDO DE 8 BITS . 232
8.3 C ONJUNTOS DE CARACTERES EXISTENTES EN U NICODE . 233
8.4 O PCIONES DE CODIFICACI ÓN DEL B LOC DE NOTAS DE W INDOWS . 236
8.5 C OMPROBAMOS EL BOM A ÑADIDO POR EL B LOC DE NOTAS . 236
8.6 U N IDENTIFICADOR DE VARIABLE EN JAPON ÉS . 237
8.7 D IFERENCIAS ENTRE UNA CADENA U NICODE Y UNA ANSI. 240
8.8 U SO DE CADENAS ANSI CON P ÁGINAS DE C ÓDIGOS ALTERNATIVAS . 242
8.9 C ONTENIDO REAL DE CADA VARIABLE . 245
8.10 GUI DEL PROGRAMA PARA CARGAR / GUARDAR CON CODIFICACI ÓN . 247
8.11 E L PROGRAMA EN FUNCIONAMIENTO MOSTRANDO LA
CONFIGURACI ÓN DE UN ARCHIVO RECI ÉN ABIERTO . 251
8.12 V ISTA PARCIAL DEL CONTENIDO DEL ARCHIVO CSV. 254
8.13 D EFINICI ÓN DE LOS CAMPOS DEL ARCHIVO CSV. 255
8.14 L A APLICACI ÓN MOSTRANDO LOS DATOS LE ÍDOS DEL ARCHIVO CSV. 257
8.15 C ONFIGURACI ÓN DE LA CODIFICACI ÓN PARA UNA CONEXI ÓN A
I NTERBASE . 258
9.1 C ONFIGURACI ÓN DEL M ÉTODO DE AUTENTICACI ÓN . 267
9.2 L ISTA DE CONEXIONES Y PAR ÁMETROS . 272
9.3 S ELECCI ÓN DE CAMPOS CONCRETOS EN UNA CONSULTA . 273
9.4 C ONSULTA CON FILTRADO DE FILAS Y SELECCI ÓN DE COLUMNAS . 275
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
28 LISTA DE FIGURAS
9.5 E LEMENTOS A INTRODUCIR EN EL FORMULARIO . 278
9.6 E L PROGRAMA EN FUNCIONAMIENTO MOSTRANDO UNA P ÁGINA DE
DATOS . 281
9.7 O PCIONES DE ACTUALIZACI ÓN DE UN CONJUNTO DE DATOS . 283
9.8 A JUSTAMOS LA CONSULTA A EJECUTAR . 285
9.9 S E LOCALIZA LA FILA A ACTUALIZAR USANDO LA CLAVE PRIMARIA . 286
9.10 L A CL ÁUSULA WHERE USA LA CLAVE PRIMARIA Y LOS CAMPOS
MODIFICADOS . 287
9.11 L A SENTENCIA DE ACTUALIZACI ÓN PODR ÍA AFECTAR A M ÚLTIPLES
FILAS . 288
9.12 C ONSULTA CON RELACI ÓN ENTRE DOS TABLAS . 289
9.13 L A CLAVE PRIMARIA EMPLEADA NO ES LA CORRECTA . 290
9.14 E STABLECEMOS LA CLAVE PARA ACTUALIZAR . 291
9.15 L A ACTUALIZACI ÓN SE COMPLETA SIN PROBLEMAS . 292
9.16 I NTRODUCIMOS LA CONSULTA Y ACCEDEMOS AL EDITOR DEL
COMPONENTE TFDU P D A T E SQL. 294
9.17 S ELECCIONAMOS LAS COLUMNAS PARA CADA CATEGOR ÍA . 294
9.18 A JUSTAMOS LAS SENTENCIAS SQL SI ES PRECISO . 295
9.19 S OLICITAMOS AL SERVIDOR LOS DATOS AGREGADOS Y AGRUPADOS . 297
9.20 C ONFIGURAMOS EL PAR ÁMETRO A FACILITAR A LA CONSULTA . 300
9.21 E L PROGRAMA EJECUTANDO LA FUNCI ÓN . 301
9.22 P ROPIEDADES DEL COMPONENTE TFDS C R I P T . 304
9.23 E DICI ÓN DEL script SQL. 305
9.24 O PCIONES PARA PROBAR EL GUI ÓN EN LA FASE DE DISE ÑO . 305
9.25 C UADRO DE DI ÁLOGO CON LA EJECUCI ÓN DEL SCRIPT. 308
10.1 P ROPIEDADES QUE CONTROLAN LA GESTI ÓN DE TRANSACCIONES . 316
10.2 N O ES POSIBLE OBTENER UN BLOQUEO SOBRE LA FILA . 322
10.3 P ROPIEDADES DEL COMPONENTE TFDE V E N T A L E R T E R . 324
10.4 N UEVAS PROPIEDADES EN EL COMPONENTE TFDQ U E R Y . 326
10.5 C ONFIGURACI ÓN DEL EVENTO A VIGILAR EN LA BASE DE DATOS . 328
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LISTA DE FIGURAS 29
10.6 F ORMULARIO PARA CONTROLAR TRANSACCIONES Y EDITAR LAS
CATEGOR ÍAS . 329
11.1 F ORMULARIO PARA PROBAR EL MODO DESCONECTADO . 337
11.2 E LEMENTOS EN LA INTERFAZ DE USUARIO . 345
11.3 L A MODIFICACI ÓN SIMULT ÁNEA GENERA UN ERROR . 348
11.4 E NLAZAMOS EL M ÓDULO DE DATOS CON EL NUEVO FORMULARIO . 352
11.5 E LEMENTOS DEL FORMULARIO DE RESOLUCI ÓN DE CONFLICTOS . 353
11.6 L ISTA DE ACCIONES EN EL TC O M B O B O X . 353
11.7 E L PROGRAMA INTENTADO SOLVENTAR UN CONFLICTO . 356
12.1 D ISTRIBUCI ÓN DEL CLIENTE I NTER BASE CON LA APLICACI ÓN . 362
12.2 C ONFIGURACI ÓN DEL CONTROLADOR F IRE DAC PARA I NTER BASE . 363
12.3 I NFORMACI ÓN SOBRE I NTER BASE S ERVER . 365
12.4 C ONFIGURACI ÓN DE LA CODIFICACI ÓN A EMPLEAR . 368
12.5 O PCIONES DE MANTENIMIENTO . 369
12.6 C OMPONENTES DE SERVICIO PARA I NTER BASE . 369
13.1 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN DATA S NAP. 377
13.2 D OCUMENTO JSON OBTENIDO A PARTIR DEL TJSONO B J E C T . 391
14.1 C OMPONENTES PARA SERVIDORES DATA S NAP. 396
14.2 O PCI ÓN PARA INICIAR EL ASISTENTE DE SERVIDOR DATA S NAP. 398
14.3 S ELECCI ÓN DEL TIPO DE CONTENEDOR . 399
14.4 C OMPONENTES A INCLUIR EN EL SERVIDOR . 400
14.5 C ONFIGURAMOS Y PROBAMOS EL PUERTO DE COMUNICACI ÓN . 401
14.6 C OMPONENTES EN EL M ÓDULO CONTENEDOR . 402
14.7 E L CORTAFUEGOS DE W INDOWS NOTIFICA QUE EL SERVIDOR
DEMANDA COMUNICACI ÓN POR RED . 404
14.8 D EFINIMOS LA CONEXI ÓN PARA ACCEDER AL SERVIDOR DATA S NAP. 405
14.9 E XAMINAMOS EL SERVICIO DESDE EL E XPLORADOR DE DATOS . 406
14.10 C OMPOSICI ÓN DE LA INTERFAZ Y COMPONENTES DEL CONSUMIDOR . 407
14.11 L ANZAMOS EL ASISTENTE PARA GENERAR EL M ÓDULO CLIENTE . 409
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
30 LISTA DE FIGURAS
14.12 E SPECIFICAMOS EL TIPO DE SERVIDOR DATA S NAP AL QUE SE
QUIERE ACCEDER . 410
14.13 FACILITAMOS LOS PAR ÁMETROS DE COMUNICACI ÓN CON EL
SERVIDOR . 411
14.14 AGREGAMOS AL FORMULARIO REFERENCIAS A LOS M ÓDULOS
CLIENTE . 412
14.15 E L CLIENTE CON LAS DOS V ÍAS PARA CONSUMIR EL SERVICIO . 413
14.16 P ODEMOS CONTROLAR EL ESTADO DEL SERVIDOR . 415
14.17 L A CLASE CON LOS M ÉTODOS DE SERVICIO SER Á DESCENDIENTE
DE TDSS E R V E R M O D U L E . 416
14.18 C OMPONENTES EN EL M ÓDULO DE CLASES DEL SERVIDOR DATA S NAP. 417
14.19 T OMAMOS EL PROCEDIMIENTO DEL E XPLORADOR DE DATOS . 419
14.20 I NTRODUCIMOS LA CONSULTA QUE QUEREMOS EJECUTAR . 420
14.21 O BTENEMOS LOS DATOS DEL SERVIDOR EN EL DISE ÑADOR . 421
15.1 S ELECCIONAMOS EL TIPO DE APLICACI ÓN CONTENEDORA DEL
SERVIDOR . 427
15.2 E LEGIMOS LOS ELEMENTOS A INCLUIR EN EL PROYECTO . 428
15.3 C OMPONENTES AGREGADOS POR EL ASISTENTE AL M ÓDULO WEB . 430
15.4 C ONFIGURACI ÓN DE LAS EXTENSIONES DE ARCHIVOS ACEPTADAS . 431
15.5 S ELECCI ÓN DEL TIPO DE proxy A GENERAR . 432
15.6 E DICI ÓN DE LAS ACCIONES ASOCIADAS AL M ÓDULO WEB . 433
15.7 C ONFIGURAMOS LAS PETICIONES QUE SE ATENDER ÁN . 435
15.8 F ORMULARIO DE CONTROL DEL SERVIDOR DATA S NAP REST. 436
15.9 L LAMADA AL SERVICIO DESDE EL NAVEGADOR CON PETICI ÓN GET. 438
15.10 L LAMADA DE TIPO POST CON EL FORMULARIO DE INVOCACI ÓN . 439
15.11 E JECUTAMOS LA SOLICITUD DESDE EL DISE ÑADOR DE D ELPHI . 443
15.12 E XAMINAMOS LA RESPUESTA OBTENIDA DEL SERVICIO . 443
15.13 I NTERFAZ DE USUARIO DEL CLIENTE REST D ELPHI . 444
15.14 C ONFIGURACI ÓN DE LA PETICI ÓN PARA CONSUMIR EL SERVICIO . 446
15.15 S E FACILITAN LOS PAR ÁMETROS QUE PRECISA EL SERVICIO . 447
15.16 C ONFIGURAMOS EL COMPONENTE TP A G E P R O D U C E R . 456
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LISTA DE FIGURAS 31
15.17 AGREGAMOS UNA NUEVA ACCI ÓN AL M ÓDULO WEB PARA
DEVOLVER LA P ÁGINA . 457
15.18 E L CLIENTE REST J Q UERY M OBILE EN FUNCIONAMIENTO . 458
15.19 C OMPONENTES A INCLUIR EN EL M ÓDULO DE DATOS DEL SERVIDOR . 460
15.20 D OCUMENTO JSON CONTENIENDO EL CONJUNTO DE DATOS . 463
15.21 E L PROYECTO NECESITA UN M ÓDULO REST DE CLIENTE PARA
ACCEDER AL SERVIDOR . 464
15.22 C OMPONENTES EN EL M ÓDULO DE DATOS . 465
15.23 E L CLIENTE PUEDE MODIFICAR LOS DATOS FACILITADOS POR EL
SERVIDOR REST. 467
16.1 E JECUTABLES CON LA VERSI ÓN DE DESARROLLO DEL SERVIDOR Y
CONSOLA EMS. 472
16.2 C OMPONENTES PARA ACCEDER A LOS SERVICIOS DE EMS. 473
16.3 A SISTENTES PARA DESARROLLO DE PAQUETES EMS. 473
16.4 P RIMER PASO DEL ASISTENTE DE CONFIGURACI ÓN DE EMS. 475
16.5 E L ASISTENTE CONFIRMA LA CONFIGURACI ÓN DE EMS. 475
16.6 C ONSOLA DE CONTROL DEL SERVIDOR EMS. 476
16.7 P ROGRAMA DE CONTROL DE LA CONSOLA DE DESARROLLO . 477
16.8 C ONSOLA DE DESARROLLO DE EMS. 477
16.9 E N EL REGISTRO DE EVENTOS APARECEN LOS RECURSOS
REGISTRADOS . 478
16.10 R ECUPERAMOS LA LISTA DE GRUPOS REGISTRADOS . 479
16.11 O BTENEMOS DETALLES DE UN GRUPO CONCRETO . 480
16.12 C REAMOS UN NUEVO GRUPO CON LA SOLICITUD DE TIPO POST. 480
16.13 A ÑADIMOS UN USUARIO NUEVO AL GRUPO CREADO ANTES . 481
16.14 I NICIAMOS SESI ÓN EN EL SERVIDOR EMS. 482
16.15 FACILITAMOS AL SERVICIO EL token OBTENIDO TRAS INICIAR SESI ÓN . 483
16.16 E N EL REGISTRO SE APRECIA EL INICIO DE SESI ÓN . 483
16.17 C AMPOS ASOCIADOS AL REGISTRO DE INSTALACIONES . 484
16.18 M ÉTODOS PARA OPERAR SOBRE LA API DE GRUPOS DEL SERVIDOR
EMS. 485
16.19 E L CLIENTE EMS EN FUNCIONAMIENTO . 489
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
32 LISTA DE FIGURAS
16.20 Ú LTIMO PASO DEL ASISTENTE PARA PAQUETES EMS. 491
16.21 P ROBAMOS EL SERVIDOR EMS DE N ÚMEROS ALEATORIOS . 494
A.1 E LEMENTOS FUNDAMENTALES DEL IDE DE D ELPHI . 501
A.2 H ERRAMIENTAS DE PERSONALIZACI ÓN DE LOS PANELES . 503
A.3 G UARDAMOS LA CONFIGURACI ÓN ACTUAL DEL IDE. 504
A.4 B ÚSQUEDA CON IDE I NSIGHT. 505
A.5 T IPOS DE PROYECTO DISPONIBLES . 507
A.6 B ÚSQUEDA DE LA OPCI ÓN CON IDE I NSIGHT. 507
A.7 P ROYECTOS Y PLANTILLAS EN LA PALETA DE HERRAMIENTAS . 508
A.8 P LANTILLAS DE PROYECTO MULTI - DISPOSITIVO . 509
A.9 E L G ESTOR DE PROYECTOS . 510
A.10 AGREGAMOS UN NUEVO PROYECTO AL GRUPO ACTUAL . 511
A.11 L ISTA CON LAS VISTAS DE DISE ÑO DISPONIBLES . 512
A.12 P ODEMOS ROTAR LA VISTA Y DESACTIVAR LA M ÁSCARA DE
DISPOSITIVO . 513
A.13 I MPORTACI ÓN DE LOS M ÓDULOS DE LAS VISTAS . 515
A.14 V ISUALIZACI ÓN PRELIMINAR PARA CADA PLATAFORMA . 516
A.15 AGREGAMOS AL DISE ÑADOR UNA NUEVA VISTA . 517
A.16 C OMPONENTES EN LA PALETA DE HERRAMIENTAS . 518
A.17 R ELACI ÓN ENTRE LOS COMPONENTES ALOJADOS EN EL CONTENEDOR . 519
A.18 V ISTA PARCIAL DEL I NSPECTOR DE OBJETOS . 522
A.19 E DITOR DE LISTAS DE CADENAS DE CARACTERES . 523
A.20 E DITOR ESPEC ÍFICO PARA UNA PROPIEDAD DE TIPO TB R U S H . 524
A.21 L ISTA DE EVENTOS DE UN COMPONENTE TFDC O N N E C T I O N . 525
A.22 L ISTA DE OBJETOS ACCESIBLES EN EL CONTEXTO ACTUAL . 527
A.23 L ISTA DE MIEMBROS DE UN OBJETO . 528
A.24 L ISTA DE PAR ÁMETROS QUE NECESITA EL M ÉTODO . 528
A.25 VALORES V ÁLIDOS PARA UNA PROPIEDAD ENUMERADA . 529
A.26 L ISTA DE PLATAFORMAS OBJETIVO Y SU CONFIGURACI ÓN . 530
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LISTA DE FIGURAS 33
A.27 S ELECCIONAMOS LA PLATAFORMA ACTIVA . 531
A.28 AGREGAMOS UNA PLATAFORMA OBJETIVO AL PROYECTO . 532
A.29 S ELECCIONAMOS LA CONFIGURACI ÓN DE GENERACI ÓN DEL
PROYECTO . 533
A.30 ACTIVAMOS UN PUNTO DE INTERRUPCI ÓN . 535
A.31 C ONFIGURACI ÓN DE PUNTO DE INTERRUPCI ÓN . 536
A.32 C OMANDOS DE EJECUCI ÓN PASO A PASO . 537
A.33 E L VALOR DE LA VARIABLE APARECE EN UNA VENTANA EMERGENTE . 538
A.34 C UADRO DE DI ÁLOGO PARA EVALUACI ÓN DE EXPRESIONES . 539
A.35 V ENTANA CON VARIABLES BAJO SUPERVISI ÓN . 540
A.36 I NFORMACI ÓN SOBRE LAS LLAMADAS HASTA EL PUNTO ACTUAL . 541
B.1 F ORMULARIOS EN EL PROYECTO DE EJEMPLO F O R M S . 550
B.2 S EGUIMIENTO AUTOM ÁTICO DE LOS COMENTARIOS TIPO TODO. 553
B.3 L OS ELEMENTOS DEL TIPO ENUMERADO TIENEN ASOCIADO UN
VALOR . 561
B.4 E L VALOR EST Á FUERA DE LOS L ÍMITES DEL SUBRANGO . 565
B.5 L A OPCI ÓN R ANGE CHECKING EST Á DESHABILITADA POR DEFECTO . 566
B.6 C ODE I NSIGHT MUESTRA LOS MIEMBROS DEL REGISTRO . 572
B.7 AGREGAMOS UN M ÓDULO DE C ÓDIGO AL PROYECTO . 598
B.8 P LANTILLA DE C ÓDIGO PARA BUCLE F O R . 626
B.9 L ISTA CON LAS PLANTILLAS DE C ÓDIGO PREDEFINIDAS . 627
B.10 S ELECCI ÓN DE UN PERFIL PARA DAR FORMATO AL C ÓDIGO . 630
B.11 P ODEMOS COMPARAR VERSIONES Y RESTAURARLAS . 631
C.1 P ÁGINA DESDE LA QUE DESCARGAREMOS G IT. 635
C.2 C ONFIGURACI ÓN DE LA L ÍNEA DE COMANDOS DE G IT. 636
C.3 ACCESO A LA GUI Y L ÍNEA DE COMANDOS DE G IT. 637
C.4 C ONFIGURACI ÓN INICIAL DE G IT. 638
C.5 C ONFIGURACI ÓN DE G IT EN EL ENTORNO DE D ELPHI . 639
C.6 C LONACI ÓN DE UN REPOSITORIO REMOTO . 641
C.7 P ROCESO DE CLONACI ÓN DEL REPOSITORIO REMOTO . 642
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
34 LISTA DE FIGURAS
C.8 O BTENER DIRECCI ÓN DE CLONACI ÓN DESDE G ITHUB . 642
C.9 M EN Ú G IT AGREGADO AL MEN Ú CONTEXTUAL DE LOS M ÓDULOS . 645
C.10 C ONFIGURAMOS LA NUEVA OPCI ÓN PARA INVOCAR A git init. 646
C.11 U SAMOS LA OPCI ÓN PARA INICIALIZAR EL NUEVO REPOSITORIO
LOCAL . 647
C.12 O PCIONES DE G IT ASOCIADAS AL PROYECTO . 648
C.13 L ISTA DE M ÓDULOS CON CAMBIOS Y AGREGADOS AL PROYECTO . 649
C.14 M EN Ú CONTEXTUAL ASOCIADO A CADA M ÓDULO EN LA VENTANA
C OMMIT. 649
C.15 R EVISI ÓN DE LOS CAMBIOS HECHOS A UN M ÓDULO . 650
C.16 ACTUALIZAMOS NUESTRO REPOSITORIO LOCAL . 652
D.1 D ESCARGA DEL INSTALADOR DE BDE PARA D ELPHI XE8. 659
D.2 I NSTALACI ÓN DE BDE EN UN EQUIPO CON D ELPHI XE8. 659
D.3 L OCALIZAMOS EL PAQUETE AGREGADO POR EL INSTALADOR . 660
D.4 ACTIVAMOS EL PAQUETE DE COMPONENTES BDE. 661
D.5 C OMPONENTES BDE EN LA PALETA DE HERRAMIENTAS . 661
D.6 H ERRAMIENTA PARA IMPORTAR ALIAS . 666
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOBRE EL AUTOR
Francisco Charte Ojeda, Ingeniero informático por la Universidad de Jaén y Doc-
tor en Tecnologı́as de la información y la comunicación por la Universidad de
Granada, es autor de más de un centenar de libros sobre sistemas operativos,
lenguajes de programación y tecnologı́a, publicados en los últimos 30 años por
distintas editoriales. Su experiencia con Delphi se inicia antes de que se lanzase
la primera versión, en 1995. Desde entonces ha escrito una veintena de libros
sobre las distintas versiones de esta herramienta, incluyendo tı́tulos centrados en
el entorno y lenguaje, otros en el desarrollo de aplicaciones móviles y algunos
más dedicados al trabajo con bases de datos.
Francisco Charte Danysoft
AGRADECIMIENTOS
A pesar de que son muchos los años escribiendo, más de treinta ya, y de que
este es mi centésimo vigésimo segundo libro, la experiencia sigue siendo tan
maravillosa como cuando terminé de escribir el primero. La finalización de este
conlleva una enorme satisfacción, de la que me gustarı́a hacer partı́cipes a todos
aquellos que lo han hecho posible. Mi más sincero agradecimiento a José Luis
y los compañeros de Danysoft por confiarme este proyecto, a mis amigos por
su comprensión durante estos meses y, sobre todo, a mi familia, por su eterno,
extraordinario e incondicional apoyo.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Capı́tulo 1
INTRODUCCIÓN
Delphi siempre se ha caracterizado, desde su primera versión, por ofrecer al
desarrollador mecanismos que simplifican el trabajo con distintas bases de datos.
Actualmente, 20 años después del lanzamiento de su primera versión, el acceso
a bases de datos sigue siendo uno de los puntos fuertes de Delphi, ası́ como la
razón para que muchos profesionales lo elijan como entorno de trabajo.
Si algo ha cambiado en estas dos últimas décadas es la forma en que usamos
las aplicaciones. Hace dos décadas el dispositivo por excelencia, casi el único
disponible, era el ordenador personal. La información sobre la que operaban
los programas se encontraba almacenada en el mismo equipo, en una base de
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
40 INTRODUCCIÓN
datos local, o bien en un servidor de bases de datos departamental, generalmente
conectado a la misma red local. El escenario actual es mucho más heterogéneo,
comenzando por los tipos de dispositivos usados para ejecutar aplicaciones: or-
denadores, tabletas, teléfonos móviles e incluso dispositivos de tipo wearable
como los nuevos relojes y pulseras inteligentes. Las aplicaciones utilizadas son
nativas en unos casos y aplicaciones web en otros, de forma que la interfaz de
usuario se abre en un navegador web. La información sobre la que operan es-
tos programas puede estar almacenada localmente en el mismo dispositivo, pero
también encontrarse en un servidor remoto, en la otra esquina del mundo, o
estar distribuida.
El conjunto de bibliotecas de componentes para acceso a datos incorporadas
por Delphi ha ido evolucionando a lo largo del tiempo, dando cobertura a todas
esas nuevas necesidades. El objetivo de este libro es mostrar al lector cómo
puede usar Delphi en los diferentes contextos esbozados en las tres siguientes
secciones de esta introducción.
1.1 Aplicaciones móviles
El número de dispositivos móviles en uso ya supera al número total de per-
sonas que habitan el planeta. Es habitual que aparte de nuestro ordenador per-
sonal también contemos con una tableta, obviamente un teléfono móvil y quizá
también con un reloj inteligente. Todos estos gadgets tienen, en mayor o menor
medida, capacidad para ejecutar aplicaciones, programas que, por regla general,
necesitarán datos para realizar su trabajo.
NOTA
Con Delphi podemos crear aplicaciones móviles nativas para iOS y An-
droid, ası́ como aplicaciones web accesibles desde prácticamente cualquier
dispositivo, móvil o no.
La información usada por una aplicación móvil puede alojarse en el propio
dispositivo en que se ejecuta. Existen versiones especı́ficas de gestores de bases
de datos relacionales (RDBMS en adelante) para los sistemas operativos móviles
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
APLICACIONES WINDOWS/OS X 41
más difundidos. Un ejemplo de ello es InterBase ToGo. En este escenario los
programas precisan un mecanismo de acceso a datos local, ya que el RDBMS se
ejecuta en la misma máquina, no siendo necesario el uso de conexiones hacia el
exterior.
Un programa que se ejecuta en un dispositivo móvil también puede conectar
con un RDBMS remoto, operando en este caso bajo la tradicional arquitectura
cliente/servidor. Para ello el dispositivo deberı́a contar con una conexión a la red
donde se ejecuta el RDBMS, ya sea directa o a través de Internet.
1.2 Aplicaciones Windows/OS X
Las aplicaciones de escritorio, diseñadas para aprovechar la potencia de los or-
denadores que ejecutan Windows y OS X, han sido tradicionalmente las que
más necesidades de mecanismos de acceso a datos han presentado. Actualmente
algunas tabletas y teléfonos son prácticamente tan potentes como estos orde-
nadores, pero existe una gran diferencia entre ambos tipos de dispositivos: la
capacidad de almacenamiento.
Un ordenador, ya sea portátil o de escritorio, suele contar con un uno o más
discos para almacenamiento de datos, con una capacidad total que multiplica
por varias veces las de los móviles y tabletas. Estos últimos raramente superan
los 32-64 GB1 de almacenamiento, mientras que la mayorı́a de ordenadores mo-
dernos cuentan ya con 1 TB o más. Por ello resulta bastante corriente que el
usuario almacene en su propia máquina gran parte de la información con que ha
de trabajar, empleando aplicaciones que operan sobre bases de datos locales.
Lo anterior es especialmente cierto cuando la actividad del usuario no está
vinculada a alguna empresa u organización, sino que se desempeña de manera
individual. En las empresas, sobre todo a partir de cierto tamaño, los ordenadores
suelen estar conectados a un servidor de datos departamental o central, depen-
diendo de la estructura de la organización. Son situaciones en las que se recurre
principalmente a la arquitectura cliente/servidor, con RDBMS como Oracle o
1
Estas configuraciones son las usuales en 2015, pero probablemente dicha capacidad se
incremente de manera significativa en el futuro.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
42 INTRODUCCIÓN
SQL Server que, dependiendo de la configuración hardware, están preparados
para atender a miles de usuarios de forma simultánea.
1.3 Aplicaciones web
En las dos secciones previas se asume que las aplicaciones son nativas2 , por lo
que tienen acceso a los servicios necesarios para conectar con el RDBMS, ya
sea local o remoto. Si el programa en cuestión es una aplicación web, accesible
desde cualquier tipo de dispositivo, lo que ejecuta en el equipo del usuario es
únicamente la interfaz, existiendo otra parte que opera en un servidor y que, a su
vez, conectará con el RDBMS. Este es posiblemente el escenario más habitual
en la actualidad: el de una aplicación distribuida.
NOTA
Las aplicaciones web también pueden almacenar información local-
mente, ya sea mediante cookies o usando desde JavaScript el servicio
localStorage de HTML5.
Las aplicaciones distribuidas se estructuran en varias capas, de ahı́ que en oca-
siones también se use la denominación aplicación multi-capa. La arquitectura
más habitual es la que utiliza tres capas:
La interfaz de usuario es la capa que se ejecuta en el dispositivo del usuario,
ya sea este un móvil, una tableta o un ordenador.
En el servidor web se ejecuta la capa con la lógica de procesamiento, en-
cargada de responder a las solicitudes de la capa de interfaz. Para ello se
puede usar el mecanismo tradicional, sirviendo páginas, o bien recurrir el
esquema REST (Representational State Transfer) habitual de los servicios
web.
2
En algunos casos puede ser preciso un intérprete o runtime, como ocurre con las apli-
caciones Java que precisan de la máquina virtual o JVM, pero asumiremos que estas también
son aplicaciones nativas.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SERVICIOS DE ACCESO A BASES DE DATOS Y DELPHI 43
La capa anterior será la que, cuando se precise, conecte con el RDBMS
que se ejecuta en la tercera capa, la capa de datos. Aunque habitualmente
estas dos últimas capas se ejecutarán en servidores conectados entre sı́ lo-
calmente, también cabe la posibilidad de que el servidor de datos sea un
servicio remoto respecto al servidor web.
Si bien esta arquitectura es, como se ha dicho antes, la más usual, nada impide
la existencia de capas adicionales. Además es una arquitectura no exclusiva de
las aplicaciones web, también puede utilizarse con aplicaciones móviles o de
escritorio. La principal diferencia estriba en que la interfaz de usuario será una
GUI (Graphics User Interface) nativa, en lugar de un documento HTML/CSS
que es necesario abrir en un navegador web.
1.4 Servicios de acceso a bases
de datos y Delphi
La incorporación de mecanismos propios de acceso a bases de datos ha sido
siempre uno de los puntos fuertes de Delphi desde su lanzamiento, en 1995,
convirtiéndose ası́ en la herramienta ideal para el desarrollo de las clásicas apli-
caciones de gestión, ocupando el espacio dejado por productos mı́ticos como
dBase, FoxPro o Clipper.
Con el paso del tiempo las necesidades de los programadores han ido evolu-
cionando, a medida que las aplicaciones nativas de escritorio fueron dejando
paso a las aplicaciones web, en primer término, y a las móviles, en segundo. Los
servicios de acceso a datos ofrecidos por Delphi también se fueron adecuando a
esas necesidades, haciendo posible el diseño de soluciones distribuidas y también
embebidas.
Esta sección es un viaje rápido por la historia de los servicios de acceso a bases
de datos incorporados por Delphi a lo largo de los años, desde el hoy obsoleto
BDE hasta el actual FireDAC.
El objetivo que se persigue con este recorrido es obtener una visión general
que nos permita comprender cómo se ha llegado al punto actual, ası́ como la
razón de que FireDAC sea el mecanismo que deberı́amos utilizar preferente en
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
44 INTRODUCCIÓN
el desarrollo de nuestros nuevos proyectos, si bien todas las demás opciones
permanecen también abiertas.
NOTA
No es necesario conocer absolutamente nada sobre BDE, IBX y los
demás motores de acceso a datos para seguir este libro y comenzar a traba-
jar con FireDAC en las actuales versiones de Delphi.
1.4.1 BDE
BDE (Borland Database Engine) es la denominación del primer mecanismo de
acceso a datos ofrecido por Delphi. BDE era un producto basado en bibliote-
cas de acceso a datos usadas previamente por Borland en Paradox3 y en Turbo
Pascal4 , cuya interfaz de programación era conocida como IDAPI (Integrated
Database Application Program Interface).
Mediante BDE las aplicaciones podı́an acceder directamente a bases de datos
dBase, Paradox, Access y FoxPro, gestores de datos locales todos ellos. Si
se agregaba el módulo SQL Links también se podı́a acceder a RDBMS como
DB2, Informix, InterBase, Sybase y Oracle en una configuración cliente/servi-
dor. Asimismo se ofrecı́a un controlador que actuaba como puente con ODBC
(Open Database Connectivity), abriendo ası́ la puerta a usar cualquier base de
datos accesible mediante esta vı́a. En la Figura 1.1 se ha representado la estruc-
tura tı́pica de las soluciones basadas en BDE.
Con BDE Delphi introdujo una arquitectura de componentes que terminó
influenciando el desarrollo de otras soluciones de acceso a datos (véanse los
apartados siguientes). La base de datos estaba representada por un componente
TDatabase, en el que se alojaba la información necesaria para conectar con
3
Paradox era una aplicación de gestión de bases de datos local, la categorı́a a la que
pertenece Microsoft Access, y en su tiempo competı́a con el entonces rey del mercado que era
dBase. Finalmente Borland terminó adquiriendo en 1991 la empresa Asthon Tate, desarro-
lladora de dBase.
4
El predecesor de Delphi contaba con una biblioteca complementaria de acceso a datos
conocida como Database Toolbox.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SERVICIOS DE ACCESO A BASES DE DATOS Y DELPHI 45
Figura 1.1 ARQUITECTURA DE UNA SOLUCI ÓN BASADA EN BDE
ella. Mediante los componentes TTable y TQuery se operaba sobre tablas de
datos y con consultas SQL. Un componente TDataSource, actuando como in-
termediario con los anteriores, permitı́a conectar los datos con los controles que
formaban la interfaz de usuario.
NOTA
BDE no solo incluı́a los componentes necesarios para comunicarse con
las bases de datos enumeradas, sino que también incorporaba el motor de
dBase y Paradox. Esto permitı́a a las aplicaciones Delphi trabajar con esos
tipos de bases de datos sin necesidad de instalar dichos productos. A cambio
la instalación de BDE incluye elementos que pueden no ser necesarios para
nuestros proyectos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
46 INTRODUCCIÓN
BDE es una solución lanzada hace ahora más de dos décadas y cuyo
desarrollo se detuvo hace tiempo. Los mayores inconvenientes de este
mecanismo de acceso a datos son:
Depencia del sistema operativo: BDE y sus controladores son una solución
especı́fica Win32. Esto significa que no podremos usarlo en aplicaciones de
64 bits desarrolladas para Windows, ni tampoco en otros sistemas como OS
X, Android o iOS. Optar por BDE, por tanto, implicarı́a perder una de las
grandes ventajas que nos ofrecen las últimas versiones de Delphi: el
desarrollo de soluciones multi-dispositivo.
Despliegue e instalación complejos: La instalación de BDE en los equipos
donde va a desplegarse una aplicación Delphi es, aparte de relativamente
pesada por la inclusión de los motores de dBase y Paradox, compleja5 , ya
que se precisa escribir datos de configuración e n e l r egistro d e Windows,
para lo cual es necesario contar con privilegios de administrador. Si hay
más de una aplicación usando BDE en el sistema pueden aparecer conflictos
entre ellas a raı́z de esos parámetros de configuración.
Sin Unicode: BDE no contempla el uso de Unicode ni lo hará nunca, lo cual
complica su uso con las versiones recientes de Delphi6 , aparte de limitar
nuestras aplicaciones al no poder utilizar alfabetos que usan caracteres no
existentes en las codificaciones tradicionales.
Sin soporte: El desarrollo de BDE se detuvo hace mucho tiempo. Delphi 6,
lanzado en el año 2000, incorporó como novedad dbExpress, el mecanismo
de acceso a datos llamado a sustituir a BDE. En el año 2002 SQL Links fue
declarado como obsoleto (deprecated). BDE es, por tanto, una solución
anticuada y que no evolucionará más, para la que no se resolverán fallos y
para la que el fabricante ya no da soporte.
Si las razones anteriores no son suficientes para decidirnos a abandonar BDE,
debemos tener en cuenta que a partir de la versión XE7 BDE ya no se distribuye
como parte del producto No obstante, puede descargarse e instalarse por sepa-
rado (véase el Apéndice D), una opción que nos permitirı́a hacer la transición
hacia alguna de las demás opciones discutidas a continuación.
5
Antes de que una aplicación BDE pueda funcionar es preciso configurar los alias de
bases de datos y configurar los controladores que vayan a utilizarse.
6
El tipo String de Delphi usa por defecto Unicode desde Delphi 2009.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SERVICIOS DE ACCESO A BASES DE DATOS Y DELPHI 47
1.4.2 IBX
Además de dBase, la adquisición de Asthon Tate por parte de Borland también
incorporó al abanico de productos de esta última empresa un RDBMS llamado
InterBase7 . Aunque Borland terminó deshaciéndose de sus otros productos de
bases de datos, Paradox por ejemplo fue vendido a Novell, continuó desarro-
llando InterBase como el RDBMS propio de la empresa, enfoque que también
ha mantenido Embarcadero. Actualmente contamos con versiones de InterBase
tanto para servidores de datos como para operar bases de datos embebidas, in-
cluso en dispositivos móviles (el antes mencionado InterBase ToGo).
Dado que el fabricante de Delphi contaba con un RDBMS propio, era lógico
que la herramienta de desarrollo incorporase componentes capaces de aprovechar
las caracterı́sticas especı́ficas de dicho RDBMS. Esa biblioteca de componentes
a medida es IBX (InterBase eXpress), lanzada en versión beta junto con Delphi
5 y que ha formado parte de todas las versiones de Delphi posteriores.
Los componentes IBX están diseñados para comunicarse directamente con el
software cliente de InterBase (véase la Figura 1.2), lo cual hace innecesarios los
controladores intermedios existentes en BDE. En consecuencia el acceso a los
datos pasa por menos capas, lo cual redunda en un mayor rendimiento. Una
ventaja adicional es que las aplicaciones Delphi pueden aprovechar las carac-
terı́sticas especı́ficas que ofrece InterBase, incluso existen componente IBX para
tareas de administración, prescindiendo ası́ de herramientas externas.
NOTA
Los componentes IBX se agrupan en dos categorı́as: componentes de
acceso a datos, equivalentes a los que ofrece BDE, y componentes de admi-
nistración. Estos últimos permiten a las aplicaciones obtener información
estadı́stica del funcionamiento del servidor, efectuar copias de seguridad de
las bases de datos, etc., usando para ello las funciones ofrecidas por la API
de InterBase.
7
Asthon Tate adquirió en 1988 la tecnologı́a de InterBase de Interbase Software Corpo-
ration, una empresa fundada en 1984 centrada en la creación de software de bases de datos
relacionales para estaciones de trabajo Sun y sistemas DEC VAX.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
48 INTRODUCCIÓN
Figura 1.2 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN IBX.
La principal, y casi la única, desventaja de IBX es que se trata de una solución
a medida de un RDBMS. Desarrollar una aplicación Delphi usando IBX dificul-
tará una futura transición a otro RDBMS, ya que nos verı́amos forzados a usar
otro mecanismo de acceso a datos. Esto supondrı́a cambiar todos los compo-
nentes utilizados en el proyecto por otros distintos.
1.4.3 dbGo
En la segunda mitad de los años 90 Microsoft desarrolló para Windows sus pro-
pios servicios de acceso a datos, apoyándose para ello en la infraestructura COM
(Component Object Model), su modelo de componentes software. Es en este
contexto donde aparecen los componentes ADO (ActiveX Data Objects) y los
controladores OLE DB, ofreciendo una solución de acceso a bases de datos de
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SERVICIOS DE ACCESO A BASES DE DATOS Y DELPHI 49
tipo genérico, independientes tanto de la base de datos como del lenguaje de
programación utilizado. La interfaz para las aplicaciones era uniforme, sólo se
precisaba cambiar de controlador OLE DB para operar sobre un RDBMS u otro.
A fin de aprovechar estos nuevos servicios, Delphi i ncorporó en su versión 5
un nuevo conjunto de componentes denominados ADOExpress. La biblioteca
cambió su nombre por dbGo en Delphi 6, denominación que ha mantenido hasta
la actualidad.
Figura 1.3 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN DB G O .
Los componentes dbGo actúan a modo de envoltorios (wrappers) en torno a
los servicios ofrecidos por ADO, facilitando la comunicación con los distintos
proveedores OLE DB disponibles. Un proveedor OLE DB es como un contro-
lador BDE, actuando como intermediario entre la aplicación y el software cliente
de la base de datos con la que vaya a trabajarse. Hay disponibles proveedores
OLE DB para diversos RDBMS, entre ellos Microsoft SQL Server, ası́ como un
puente OLE DB-ODBC que facilita el acceso a cualquier origen de datos para el
que exista un controlador ODBC.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
50 INTRODUCCIÓN
El inconveniente de dbGo es que se trata de una solución especı́fica de un
fabricante, válida únicamente para aplicaciones que se ejecutarán en equipos con
Windows. Cualquier proyecto con objetivos multiplataforma, por tanto, descarta
ya de entrada esta solución. Sin embargo para aplicaciones que únicamente van
a utilizarse en Windows dbGo puede ser una buena alternativa, dado que facilita
el trabajo con fuentes de datos muy habituales en dicho sistema operativo como
son las hojas de cálculo Excel o las bases de datos Access.
1.4.4 dbExpress
El lanzamiento de Delphi 6 vino acompañado de un nuevo producto que habı́a
sido esperado durante mucho tiempo por los usuarios de Delphi: una versión
para GNU/Linux de su entorno de desarrollo preferido, con su correspondiente
compilador, biblioteca de componentes y otras utilidades. Ese nuevo producto se
denominó Kylix y conllevó algunas novedades más. Quizá las más destacables
fueron la biblioteca de componentes cross-platform CLX y el nuevo mecanismo
de acceso a bases de datos dbExpress.
La VCL es una biblioteca de componentes nacida en Windows y con estre-
chos vı́nculos con el sistema operativo de Microsoft, razón por la que hubo que
desarrollar una nueva, la mencionada CLX, pensada para ser multiplataforma
desde un principio. La CLX estaba llamada a sustituir a la VCL, pero el limitado
éxito de Kylix, del que solo existieron dos versiones más, provocó que tanto el
producto como la biblioteca de componentes fuesen abandonadas.
NOTA
La última versión de Kylix, la versión 3, fue presentada en 2002 y sus
caracterı́sticas eran similares a las de Delphi 7, en cuanto a compiladores
(se incluı́a Delphi y C++), entorno de desarrollo, biblioteca CLX y software
de acceso a datos dbExpress.
Análogamente, dbExpress fue diseñada como una solución de acceso a datos
multiplataforma, sin vı́nculos con Windows a diferencia de BDE, y su objetivo
era sustituir a esta última. En contraste con la suerte que corrió la CLX, dbEx-
press siguió evolucionándose en versiones posteriores de Delphi y sigue siendo
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SERVICIOS DE ACCESO A BASES DE DATOS Y DELPHI 51
una de las opciones existentes actualmente a la hora de desarrollar aplicaciones
con acceso a datos. La principal ventaja de dbExpress es que se trata de una
solución escrita totalmente en el propio lenguaje Delphi, por lo que los contro-
ladores necesarios para acceder a las bases de datos pueden integrarse directa-
mente en la aplicación.
Aunque en la actualidad no existe una versión de Delphi para GNU/Linux,
sı́ que es posible desarrollar aplicaciones para OS X. Estas aplicaciones multi-
plataforma no pueden usar BDE o dbGo, pero sı́ dbExpress ya que esta es una
solución que puede compilarse para distintos sistemas.
Figura 1.4 A RQUITECTURA DE UNA SOLUCI ÓN BASADA EN DB E XPRESS .
Los controladores dbExpress están diseñados en base a un mı́nimo común de-
nominador de los distintos RDBMS, por lo que no aprovechan las caracterı́sticas
especı́ficas de cada uno de ellos. Además fueron desarrollados con el rendi-
miento como principal objetivo, sacrificando en algunos casos funciones más
avanzadas a cambio de ser más ágiles en el tratamiento de los datos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
52 INTRODUCCIÓN
1.4.5 DataSnap
Los distintos frameworks de acceso a bases de datos mencionados en los aparta-
dos previos facilitan el acceso a datos locales o bien alojados en un servidor,
según la tradicional arquitectura cliente/servidor. La necesidad de centralizar el
acceso a los datos en un servidor independiente del que ejecuta el RBDMS, a
fin de optimizar el uso de recursos, no es nueva y dio origen a la arquitectura
distribuida en varias capas o multi-tier.
Ya en Delphi 3 se ofrecı́a una solución llamada a satisfacer dicha necesi-
dad: MIDAS (Multi-tier Distributed Application Service Suite). Esta cambió
su nombre por DataSnap en Delphi 6, denominación que mantiene a dı́a de hoy.
Originalmente DataSnap ofrecı́a fundamentalmente los servicios necesarios para
operar de manera remota sobre conjuntos de datos, transportando la información
necesaria en ambos sentidos: desde el servidor de aplicaciones al cliente y vi-
ceversa. Posteriormente se agregó la funcionalidad de poder ejecutar de forma
remota funciones (servicios) definidos en el servidor de aplicaciones.
Figura 1.5 ARQUITECTURA DE UNA SOLUCI ÓN BASADA EN DATASNAP
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SERVICIOS DE ACCESO A BASES DE DATOS Y DELPHI 53
Originalmente MIDAS se diseñó para funcionar sobre DCOM (Distributed
Componente Object Model), el modelo de componentes distribuido de Microsoft,
por lo que dependı́a de la configuración DCOM del sistema para su correcto fun-
cionamiento. Desde Delphi 2009 la implementación de DataSnap está basada
en los componentes Indy TCP, por lo que es posible comunicarse por cualquier
tipo de red basada en TCP/IP, sin dependencias respecto a DCOM. En Delphi
2010 se añadió a DataSnap soporte para solicitudes de tipo REST (Representa-
tional State Transfer) que en la actualidad, junto con JSON (JavaScript Object
Notation), es el estándar para el desarrollo de servicios web.
El modelo distribuido ofrecido por DataSnap también ha evolucionado con
el tiempo, adaptándose a la nuevas necesidades del mundo móvil en que nos de-
senvolvemos actualmente. Gracias a los DataSnap Mobile Connectors es posible
acceder a datos alojados en un servidor desde aplicaciones móviles. A esto hay
que sumar la posibilidad de usar REST desde cualquier tipo de cliente, esté o no
desarrollado con Delphi.
1.4.6 FireDAC
A pesar de ser la opción de incorporación más reciente en Delphi, en la versión
XE4 se podı́a adquirir FireDAC por separado y a partir de la versión XE5 se
incluyó como parte de la edición Professional y superiores, lo cierto es que
FireDAC no es un desarrollo completamente nuevo. Anteriormente conocido
como AnyDAC8 , esta biblioteca de componentes y controladores fue adquirida a
otra empresa, heredando más de una década de experiencia en su desarrollo.
FireDAC es una solución de acceso a datos denominada como universal. Este
apelativo se debe a que está disponible para todos los sistemas operativos con los
que podemos crear aplicaciones con Delphi: Windows, OS X, iOS y Android, y
facilita la conexión prácticamente con cualquier origen de datos: bases de datos
locales y embebidas, múltiples RDBMS y cualquier otra fuente para la que exista
un controlador ODBC o dbExpress.
Una de las grandes ventajas de FireDAC es que ofrece a los desarrolladores
un modelo unificado de acceso a los datos, sin que importe el sistema o dónde
esté alojada la información, pero al tiempo también facilita la explotación de
8
La biblioteca de componentes AnyDac, diseñada para Delphi, C++ Builder y FreePascal,
fue adquirida por Embarcadero a la empresa DA-SOFT en febrero de 2013.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
54 INTRODUCCIÓN
caracterı́sticas especı́ficas de cada RDBMS. Además FireDAC cuenta con
componentes para mantener bases de datos en memoria, incorporando su propio
motor SQL para trabajar sobre ellas.
Entre otros productos, una aplicación Delphi que use FireDAC podrá acceder
a bases de datos de escritorio Access, bases de datos embebidas SQLite e
InterBase ToGo y RDBMS como SQL Server, Oracle, DB2, MySQL, InterBase
y Firebird.
NOTA
Según la edición de Delphi con que contemos el conjunto de contro-
ladores FireDAC incluido variará, algo que hemos de tener en cuenta a
la hora de planificar el trabajo con un cierto RDBMS.
Figura 1.6 ARQUITECTURA DE UNA SOLUCI ÓN BASADA EN FIREDAC
Por su enfoque multiplataforma, su rendimiento y las caracterı́sticas avan-
zadas que ofrece, FireDAC es el mecanismo de acceso a datos preferente a la
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOBRE ESTE LIBRO 55
hora dedesarrollarnuevosproyectosconDelphi. Dependiendodesucomple-
jidad, también puede merecer la pena la conversión de proyectos ya existen-
tes,basadosenBDEoendbExpress,paraaprovecharlasventajasdeFireDAC.
DebemostenerencuentaqueBDEesunatecnologı́atotalmenteobsoleta,como
seapuntabaanteriormente,yquedbExpress,aunqueprobablementesigaaún
muchotiempopresenteenDelphi,esunabibliotecacuyodesarrollosehaestan-
cadoenfavordelaevolucióndeFireDAC.
1.5 Sobreestelibro
Elobjetivodeestelibroesdescribirloscomponentes,lasherramientasylospro-
cedimientosaseguirparaoperarconbasesdedatosaldesarrollaraplicaciones
Delphiendistintosescenarios.Nuestrapretensiónesofrecerallectorlainfor-
maciónquenecesitaráencadacasoconcreto,explicandodetalladamentecuálser
ı́alaconfiguraciónausaryacompañandodichasexplicacionesconejercicios
demostrativosquelasponganenpráctica.
Como la práctica totalidad de libros sobre programación, este está pensado
para ser leído prácticamente delante del ordenador, a fin de que se pueda ir expe-
rimentando cada paso personalmente. Para facilitar este seguimiento los
proyectos propuestos como ejercicios están a disposición del lector en
[Link]/libros/[Link] y en un
repositorio de GitHub, en [Link]/fcharte/DelphiBDD. Te
recomendamos que comiences por obtener dichos proyectos para tenerlos al
alcance del teclado a medida que avances.
NOTA
En el apéndice C se describe la instalación y uso de Git, ası́ como la
clonación de repositorios GitHub desde Delphi. No obstante, también
puede descargar directamente el paquete con los ejemplos, sin recurrir a
Git en [Link]/libros/[Link]
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
56 INTRODUCCIÓN
1.5.1 Estructura
A lo largo del libro se abordarán tres contextos de trabajo diferentes, corres-
pondiéndose estos con las tres grandes partes en que está dividido el libro. A
continuación se ofrece una descripción breve del contenido de cada una de ellas:
Acceso a datos locales: Los capı́tulos de la primera parte tratarán el acceso
a orı́genes de datos locales, alojados en el mismo dispositivo en que se
ejecuta la aplicación. Por una parte trabajaremos en proyectos dirigidos a
ordenadores con Windows u OS X y, por otra, a aplicaciones para disposi-
tivos móviles usando bases de datos embebidas. Siendo esta la configura-
cion más simple, ya que datos y programa están en la misma máquina, los
capı́tulos de esta parte también explicarán cómo usar algunas herramientas y
componentes fundamentales y de uso general.
Aplicaciones cliente/servidor: En la segunda parte del libro nos ocupare-
mos de la arquitectura de acceso a datos más popular, aquella en la que la
aplicación, ejecutándose en un dispositivo conectado a una red, se comu-
nica con un servidor de datos para operar sobre la información. Además de
los procedimientos de trabajo comunes a todos los RDBMS, que facilitan
un desarrollo unificado, también se explicará cómo acceder a caracterı́sticas
especı́ficas de productos concretos, usando para ellos componentes adecua-
dos.
Aplicaciones distribuidas: La tercera parte del libro se concentrará en las
técnicas de acceso a datos en entornos distribuidos, con clientes que pueden
ser aplicaciones Delphi en un ordenador pero también aplicaciones web en
un navegador o programas para dispositivos móviles, un servidor de apli-
caciones atendiendo peticiones de dichos clientes y un servidor de datos
conectado al anterior. En los capı́tulos de esta parte conoceremos las distin-
tas opciones a la hora de transportar y gestionar datos desde un extremo a
otro.
Al final del libro, tras los capı́tulos de estas tres partes, encontramos cuatro
apendices cuya finalidad es ayudar a los desarrolladores que no estén familia-
rizados con el lenguaje Delphi, con su entorno y con el uso de Git como sistema
de control de versiones de código fuente. Nuestro objetivo con estos apéndices
es facilitar al lector la información que pueda necesitar para comenzar a crear
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOBRE ESTE LIBRO 57
aplicaciones Delphi con acceso a bases de datos, pero obviamente es
imposible resumir en los mismos libros completos centrados en los aspectos
más genéricos de esta herramienta.
1.5.2 Notaci´on
En el texto de este libro se utilizarán distintas notaciones a fin de distinguir
mejor ciertos tipos de elementos. En el texto propiamente dicho, aparte del tipo
de letra normal, podemos encontrar también los siguientes estilos:
Destacado: El texto en negrita se utiliza puntualmente para destacar algo
importante o la primera vez que se introduce un concepto al que es necesario
prestar atención.
Términos: La letra en estilo cursiva se emplea para distinguir términos
anglosajones o bien para introducir el significado de acrónimos en dicho
idioma, habitualmente entre paréntesis siguiendo al acrónimo.
Código: Este estilo diferencia en el texto los nombres de componentes,
variables, sentencias de Delphi y, en general, cualquier elemento que pueda
formar parte del código de un programa.
I NTERFAZ: Los tı́tulos de botones, OPCIONES de menú y cualquier otro
elemento relativo a la interfaz de Delphi u otra herramienta que esté des-
cribiéndose aparecerán en este estilo. Para indicar que se ha de abrir un
menú o submenú y, a continuación, elegir una cierta opción se usará la no-
tación M EN Ú —S UBMEN Ú —O PCI ÓN.
Además de estos estilos, en el texto también se destacarán puntualmente
párrafos completos con el objetivo de aclarar o advertir de algo importante:
NOTA
Las notas se usan para destacar algo importante o aclarar algún
concepto en relación con lo que está explicándose.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
58 INTRODUCCIÓN
Las referencias a ejercicios que puedan obtenerse desde el repositorio GitHub
asociado al libro aparecerán en el texto como se muestra a continuación:
EJEMPLO 1.1 NombreProyecto
Esta notación se usará para indicar la carpeta en la que se encuentra
un cierto ejemplo y su nombre.
Finalmente, los fragmentos de código introducidos en el texto tendrán el aspecto
siguiente:
1 procedure [Link](Sender: TObject);
2 var
3 unaVariable: String;
4 begin
5 with aNotification do begin
6 Name := ’Delphi y bases de datos’; // Aquı́ un comentario
7 end;
8 end;
Listado 1.1 Código de ejemplo
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
PARTE 1
ACCESO A DATOS
LOCALES DESDE
APLICACIONES
NATIVAS
En esta primera parte del libro se introducirá el mecanismo fundamental de
acceso a datos con que cuentan las últimas versiones de Delphi: FireDAC,
usándolo en un contexto local desde aplicaciones nativas, ya sea ejecutándose
en Windows, OS X, iOS o Android.
Comenzaremos desarrollando un ejercicio muy sencillo que nos permita tener
una visión global, sin entrar en los pormenores, para después adentrarnos en
los fundamentos de FireDAC. A continuación, en los capı́tulos siguientes, nos
familiarizaremos con las herramientas del entorno de Delphi que usaremos para
desarrollar este tipo de aplicaciones: los módulos de datos, los componentes de
interfaz vinculados a un origen de datos que servirán para diseñar la interfaz de
usuario, gestores de bases de datos locales y embebidos, etc. Luego abordaremos
el uso de IB ToGo e IBLite como gestor de datos embebido, especialmente para
aplicaciones móviles. Terminaremos abordando algunos detalles relativos al uso
de FireDAC con bases de datos de escritorio, bases de datos en memoria y el
trabajo con datos Unicode.
Introducción a FireDAC 61
Herramientas BDD en Delphi 89
Interfaces de usuario con conexión a datos 123
InterBase embebido 155
Bases de datos de escritorio 181
Bases de datos en memoria 209
Bases de datos y Unicode 229
Capı́tulo 2
INTRODUCCIÓN A FIREDAC
Al desarrollar una aplicación con Delphi podemos usar FireDAC en multitud de
contextos diferentes. En los capı́tulos de este libro, según avancemos, tendremos
ocasión de conocer varios de ellos. Este capı́tulo es nuestro punto de partida, en
el que comenzaremos a fraguar los cimientos que nos permitirán ir construyendo
proyectos cada vez más elaborados y complejos.
Nuestro primer objetivo es obtener una visión general del procedimiento que
seguiremos habitualmente para trabajar con FireDAC. ¿Qué mejor modo de ha-
cerlo que a través de un ejercicio práctico? Pongámonos manos a la obra colo-
cando el primer pilar metafórico de los cimientos de los que hablábamos antes.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
62 INTRODUCCIÓN A FIREDAC
2.1 Hola FireDAC
Nos proponemos desarrollar el tı́pico programa Hola mundo que, por tradición,
se escribe siempre que se toma contacto por primera vez con un nuevo lenguaje
o herramienta. En este caso, no obstante, el objetivo no es tan simple como
la impresión de un mensaje en pantalla. Pretendemos crear una aplicación que
muestre la información almacenada en una tabla de una base de datos, sin más
funcionalidad por el momento. Para ello no precisaremos de ninguna herramienta
externa ni de un servidor datos, todos los elementos que necesitamos están in-
cluidos en Delphi.
NOTA
A partir de este punto se asume que el lector tendrá instalada en su
equipo de desarrollo una versión de Delphi que incluya FireDAC, a fin de
poder llevar a cabo por sı́ mismo los pasos que se irán describiendo en los
siguientes apartados de esta sección.
2.1.1 Inicio del proyecto
Nuestro programa tiene como única finalidad familiarizarnos con la estructura
de una aplicación simple en la que se utiliza FireDAC para acceder a una base de
datos, por lo que bastará con que podamos ejecutarla en nuestro propio equipo
de desarrollo. No obstante, si se tratase de un proyecto real probablemente nos
interesase tener también como objetivo OS X, iOS y Android. Por ello vamos a
iniciar un proyecto de tipo multi-dispositivo.
Usaremos la opción N EW —M ULTI -D EVICE A PPLICATION del menú F ILE,
tal y como se muestra en la Figura 2.1. Esto abrirá el cuadro de diálogo M ULTI -
D EVICE A PPLICATION, ofreciéndonos las plantillas disponibles. Elegiremos la
opción B LANK A PPLICATION a fin de partir de un proyecto vacı́o. Este cons-
tará inicialmente de un formulario, la superficie en la que irı́amos incluyendo
los elementos de nuestra interfaz de usuario, que se abrirá de inmediato en el
correspondiente diseñador.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HOLA FIREDAC 63
Figura 2.1 INICIAMOS UN NUEVO PROYECTO DE APLICACI ÓN MULTI-DISPOSITIVO
En la ventana P ROJECT M ANAGER, el Gestor de proyectos de Delphi, pode-
mos comprobar que ese formulario aparece como un módulo con extensión .pas
y que tiene como hijo otro módulo, en este caso con extensión .fmx. El primero
contendrá el código asociado al formulario y el segundo la definición de la in-
terfaz propiamente dicha: lista de componentes y los valores asignados a sus
propiedades.
NOTA
Con la opción que hemos elegido para crear el proyecto estamos op-
tando por utilizar la biblioteca de componentes FMX, también conocida
como Firemonkey. El diseñador para este tipo de formularios, completa-
mente multiplataforma, se denomina FireUI. La alternativa, con la que la
aplicación únicamente podrı́a ser compilada para Windows, serı́a el uso de
la tradicional biblioteca VCL.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
64 INTRODUCCIÓN A FIREDAC
2.1.2 Adición de un módulo de datos
Aunque podrı́amos añadir al formulario todos los componentes que vamos a
necesitar, una buena práctica al desarrollar aplicaciones conectadas a bases de
datos es aislar todos los elementos no visuales, aquellos cuya finalidad es facili-
tar el acceso a los datos, en un módulo independiente, concretamente un módulo
de datos. Este es un contenedor, como los formularios, pero no cuenta con in-
terfaz de usuario.
En general, para agregar cualquier nuevo elemento a un proyecto o nuevo
componente a un contenedor usaremos IDE I NSIGHT1 . Para ello pulsamos F6 y
a continuación escribimos el inicio del nombre de lo que buscamos, en este caso
data module, seleccionándolo de la lista de resultados de búsqueda (véase la
Figura 2.2).
Figura 2.2 A ÑADIMOS UN M ÓDULO DE DATOS AL PROYECTO
El módulo de datos aparecerá abierto en el diseñador, completamente vacı́o.
Lo usaremos en los siguientes apartados como recipiente para alojar los compo-
nentes FireDAC con los que crearemos y accederemos a una base de datos
simple. Para ello comenzaremos agregando al módulo de datos un componente
TFDConnection. Recuerda: pulsa F6, escribe el nombre del componente y
pulsa INTRO para agregarlo al contenedor activo en el diseñador. También
1
También podrı́amos ir al menú F ILE para localizar esta misma opción, ası́ como al menú
contextual del proyecto en el Gestor de proyectos. Para añadir componentes a un contenedor
podemos buscar tanto en la ventana T OOL PALETTE (la Paleta de componentes), aparece
normalmente anclada en la parte inferior derecha del entorno, como en IDE I NSIGHT.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HOLA FIREDAC 65
puedes localizar el componente en la Paleta de componentes y hacer doble clic
sobre él o arrastrarlo y soltarlo, lo que te resulte más cómodo.
EJEMPLO 2.1 [Link]
Puedes encontrar este proyecto completo en la carpeta HolaFireDAC.
Para usarlo en tu equipo tendrás que editar la configuración del compo-
nente TFDConnection y corregir la ruta a la base de datos, usando
aquella en la que hayas clonado el proyecto.
2.1.3 Configuración de la conexión
A continuación tendremos que configurar la conexión a la base de datos, es-
tableciendo varias de las propiedades del componente TFDConnection recién
añadido al módulo de datos. Podemos usar la ventana O BJECT I NSPECTOR (el
Inspector de objetos), localizando las propiedades que nos interesen y modifi-
cando su contenido, tal y como se muestra en la Figura 2.3.
Figura 2.3 SELECCIONAMOS EL TIPO DE BASE DE DATOS
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
66 INTRODUCCIÓN A FIREDAC
La alternativa consiste en abrir el menú contextual del componente, elegir la
opción C ONNECTION E DITOR y usar el editor mostrado en la Figura 2.4 para
llevar a cabo la configuración.
Figura 2.4 A BRIMOS EL EDITOR DE PAR ÁMETROS DE CONEXI ÓN .
En ambos casos estableceremos las mismas propiedades, asignándoles los va-
lores enumerados a continuación:
DriverName: Esta propiedad establece el controlador FireDAC a utilizar.
Tiene asociada una lista desplegable con todas las opciones disponibles en
nuestro sistema. Elegiremos la opción SQLite.
Params.Database2 : Contiene el nombre de la base de datos y la ruta
en que se encuentra. En este caso, al tratarse de una base de datos local
alojada en un archivo, esa ruta será el camino a la carpeta en la que ya existe
2
En el Inspector de objetos la propiedad Params tiene un simbolo + a su izquierda, con
el que podemos desplegarla y acceder a sus subpropiedades. En la ventana C ONNECTION
E DITOR la propiedad aparece como Database.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HOLA FIREDAC 67
o donde se creará la base de datos. Seleccionamos la carpeta donde tenemos
el proyecto e introducimos [Link] como nombre de archivo.
LoginPrompt: Mediante esta propiedad se indica a FireDAC si ha de
solicitar credenciales de acceso a la base de datos o no. Por defecto está
marcada, su valor es True. En este caso le asignaremos el valor False,
desmarcándola, ya que no es preciso ese paso para acceder a una base de
datos SQLite.
Una vez establecidas estas tres propiedades, procederemos a dar el valor
True a la propiedad Connected para activar la conexión con la base de datos.
Dato que esta no existe, la configuración por defecto del controlador para SQLite
determina que se procederá a su creación (mira el valor por defecto de la propie-
dad [Link]). Lo que conseguimos, por tanto, es crear el archivo
indicado por la propiedad [Link], inicialmente vacı́o pero ya
preparado para operar sobre él como una base de datos SQLite.
NOTA
Puedes abrir la ventana C ONNECTION E DITOR y hacer clic en el botón
T EST para comprobar que la conexión con la base de datos es satisfactoria.
2.1.4 Creación de una tabla
Llegados a este punto tenemos una base de datos SQLite vacı́a. Para poder al-
macenar alguna información en ella antes es necesario definir, como mı́nimo, la
estructura de una nueva tabla. Para ello reproduciremos los pasos indicados a
continuación:
1. Abrimos la ventana C ONNECTION E DITOR si no la tenı́amos abierta ya,
usando para ello el menú contextual del componente TFDConnection
como se apuntó antes.
2. Accedemos a la página SQL S CRIPT de dicha ventana y escribimos en
la parte superior la sentencia SQL mostrada en el Listado 2.1, con la que
crearemos una tabla que teóricamente nos servirá para guardar reservas de
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
68 INTRODUCCIÓN A FIREDAC
asientos en algún tipo de espectáculo. Cada fila de la tabla contendrá un
identificador único, un número de asiento y un nombre de cliente.
1 CREATE TABLE Entradas(
2 id INTEGER PRIMARY KEY,
3 asiento INTEGER,
4 cliente CHAR(50)
5 );
Listado 2.1 Creación de una tabla
3. Hacemos clic en el botón RUN DE SCRIPT (véase la Figura 2.5) para eje-
cutar la sentencia. El resultado deberı́a ser la obtención de un mensaje en la
parte inferior comunicando que se ha ejecutado sin problemas.
Figura 2.5 INTRODUCIMOS LA SENTENCIA SQL PARA CREAR LA TABLA
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HOLA FIREDAC 69
2.1.5 Introducción de datos
Para que la aplicación que estamos desarrollando pueda mostrar los datos de la
tabla, esta habrá de contar con algún contenido. En este momento la tabla es
una simple estructura, sin datos en su interior. Podrı́amos utilizar la página SQL
S CRIPT de la ventana C ONNECTION E DITOR para introducir las sentencias
SQL necesarias para añadir los datos, tal y como hemos hecho para crear la
tabla. No obstante, y con el objetivo de conocer otra herramienta fundamental
del entorno de Delphi a la hora trabajar con bases de datos, vamos a emplear un
método alternativo.
En la parte superior derecha del entorno, en el espacio que ocupa original-
mente el Gestor de proyectos, encontraremos también la ventana DATA
EXPLORER (el Explorador de datos). Partiendo de ella reproducimos los
pasos siguientes:
NOTA
Si no encuentras abierta en el entorno algunas de las ventanas men-
cionadas en el texto, ve al menú principal de Delphi y utiliza las opciones
del menú V IEW para hacerlas visibles.
1. Localiza en el Explorador de datos el nodo SQLITE DATABASE, abre su
menú contextual y elige la única opción disponible: ADD NEW
CONNECTION.
2. Se abre la ventana CONNECTION EDITOR, en la que únicamente ten-
dremos que hacer clic en la propiedad Database y facilitar el camino a
la base de datos. Podemos usar el botón TEST para probar la conexión
antes de usar el botón OK para cerrar la ventana.
3. Abrimos el nodo agregado al Explorador de datos, localizamos la tabla que
habı́amos creado anteriormente, abrimos su menú contextual y elegimos la
opción VIEW, tal y como se muestra en la Figura 2.6.
4. Se abre en la parte central del entorno un editor con la estructura de la tabla
y sin contenido. Podemos introducir unas filas de datos de ejemplo, como se
ha hecho en la Figura 2.7, antes de cerrar esta página y terminar el proceso.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
70 INTRODUCCIÓN A FIREDAC
Figura 2.6 ABRIMOS LA TABLA DESDE EL EXPLORADOR DE DATOS
Figura 2.7 INTRODUCIMOS ALGUNOS DATOS EN LA TABLA
En este momento nuestra base de datos, con una única tabla, ya tiene algo de
contenido. Es todo lo que necesitamos para poder avanzar en el desarrollo de
nuestro proyecto.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HOLA FIREDAC 71
2.1.6 Otros componentes a añadir al módulo
de datos
Además del TFDConnection, mediante el que hemos creado la base de datos
y que facilitará a la aplicación la conexión con la misma, hemos de añadir al
módulo de datos otros tres componentes. Como antes, podemos pulsar F6 e
introducir su nombre para localizarlos y agregarlos. Estos componentes son:
TFDTable: Usaremos este componente para obtener todo el contenido de
la única tabla existente en la base de datos. Al agregarlo al formulario de
datos se establecerá automáticamente un vı́nculo con el TDFConnection,
pero podemos modificarlo cambiando el valor de la propiedad Connection
del TDFTable. A continuación abriremos la lista asociada a la propiedad
TableName, eligiendo la opción existente: Entradas. Finalmente dare-
mos el valor True a la propiedad Active, habilitando la conexión del
componente con la base de datos y la recuperación del contenido de la tabla.
TFDPhysSQLiteDriverLink y TFDGUIxWaitCursor: Al añadir
estos componentes al módulo incluiremos en el ejecutable el código nece-
sario para trabajar con bases de datos SQLite, sin necesidad de ningún con-
trolador externo, ası́ como los elementos de interfaz de usuario que usa
FireDAC para notificar, por ejemplo, que hay un proceso en curso. No es
necesario editar ninguna propiedad de estos componentes.
Figura 2.8 COMPONENTES INTRODUCIDOS EN EL M ÓDULO DE DATOS
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
72 INTRODUCCIÓN A FIREDAC
2.1.7 Diseño de la interfaz de usuario
A fin de visualizar la información que antes añadı́amos a la tabla de nuestra
base de datos deberemos agregar al formulario, inicialmente vacı́o, los controles
apropiados. En este caso vamos a optar por la sencillez, ya que únicamente
se pretende mostrar algunos datos, sin opciones de navegación, modificación o
búsqueda.
Añade al formulario un control TListView. Para que ocupe todo el espacio
disponible modifica su propiedad Align, dándole el valor Client. Cambia
también la propiedad ItemAppearance, como se muestra en la Figura 2.9,
seleccionando la opción ListItemRightDetail. De esta forma en la lista
se mostrará un texto principal e información de detalle a la derecha.
Figura 2.9 CONFIGURAMOS EL TLISTVIEW
Esta serı́a toda nuestra interfaz de usuario. Ahora, para que el TListView
muestre el contenido de la tabla, hemos de conectar este componente con el
TDFTable que tenı́amos en el módulo de datos. Para ello se sigue el proceso
descrito en los siguientes apartados.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HOLA FIREDAC 73
2.1.8 Enlace entre interfaz y datos
La parte final en el desarrollo de este proyecto será la creación de un vı́nculo
entre la información alojada en la base de datos, que ya tenemos seleccionada
en el componente TFDTable del módulo de datos, y la interfaz de usuario,
concretamente el componente TListView.
Lo primero que hemos hacer es agregar al formulario una referencia al módulo
de datos, de tal forma que el primero pueda usar los elementos incluidos en el
segundo. Esta acción la podemos llevar a cabo de múltiples formas. Una de las
más inmediatas consiste en elegir la opción F ILE —U SE U NIT (véase la Figura
2.10). Esta da paso a un cuadro de diálogo con la lista de módulos disponibles, en
nuestro caso solamente hay uno, del que podemos elegir el que nos interese. Este
paso3 solo hay que darlo una vez, después podrı́amos enlazar tantos controles a
componentes de datos como necesitásemos.
Figura 2.10 AGREGAMOS AL FORMULARIO UNA REFERENCIA AL M ÓDULO DE DATOS
3
Lo que hace la opción U SE U NIT es agregar a la cláusula uses del módulo actual el
nombre de otro módulo del proyecto, de forma que desde el primero es posible hacer referencia
a elementos del segundo.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
74 INTRODUCCIÓN A FIREDAC
A continuación vamos a abrir el L IVE B INDINGS D ESIGNER, la herramienta
que nos permitirá crear visualmente los vı́nculos entre datos y controles. Para
ello abrimos el menú contextual del TListView y usamos la opción B IND
V ISUALLY. La citada herramienta se abrirá como un panel en la parte inferior
del entorno, debajo del diseñador de formularios. En ella podremos ver una
pequeña tabla con el nombre del TListView como tı́tulo, y una lista de los
campos que es posible vincular, y otra que representa al TFDTable que tenemos
en el módulo de datos. En la Figura 2.11 la primera aparece a la izquierda y la
segunda a la derecha.
Figura 2.11 ENLAZAMOS COLUMNAS DE LA TABLA CON PROPIEDADES DEL CONTROL
Mediante la técnica de arrastrar y soltar, como se aprecia en la misma Figura
2.11, conectaremos la columna cliente de la tabla entradas con la propie-
dad [Link] del TListView, y la columna asiento con la propiedad
[Link]. Completado este paso, las conexiones deberı́an ser las repre-
sentadas en la Figura 2.12.
Al establecer el primero de los vı́nculos comprobaremos cómo se añaden au-
tomáticamente al formulario dos nuevos componentes: un TBindSourceDB
y un TBindingsLists. Además en el diseñador de enlaces la tabla que
representaba al TFDTable habrá sido sustituida por otra que corresponde al
TBindSourceDB. Este actúa como intermediario entre el TListView y el
TDFTable.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HOLA FIREDAC 75
Figura 2.12 CONFIGURACI ÓN FINAL DE LOS ENLACES
2.1.9 Prueba de la aplicación
Si hemos completado correctamente todos los pasos indicados en los apartados
previos, en el propio diseñador de formularios deberı́amos estar viendo, dentro
del control TListView, los datos que habı́amos introducido anteriormente en
la tabla.
Bastará con que pulsemos F9 para compilar y ejecutar el programa, cuyo re-
sultado deberı́a ser similar al mostrado en la Figura 2.13. Por cada fila podremos
ver el nombre del cliente y el asiento asignado. Si el formulario apareciese vacı́o,
o se generase algún error al ejecutar el proyecto, asegúrate de que la configu-
ración del componente TFDConnection es correcta, especialmente la ruta a
la base de datos, y de que la propiedad Active del componente TFDTable
tiene el valor True.
Lo que hemos conseguido es que una aplicación recupere información alma-
cenada en una base de datos, en este caso una tabla completa, y la muestre en una
sencilla interfaz de usuario. Para ello no hemos escrito una sola lı́nea de código
(con la excepción del SQL para crear la tabla), ha bastado con configurar ade-
cuadamente apenas media docena de componentes. En las siguientes secciones
de este capı́tulo ahondaremos un poco más en varios de esos componentes y, en
general, la forma de utilizar FireDAC para operar con bases de datos locales.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
76 INTRODUCCIÓN A FIREDAC
Figura 2.13 LA APLICACI ÓN EN FUNCIONAMIENTO
NOTA
Si quieres mostrar también el identificador que corresponde a cada
supuesto cliente, usa el L IVE B INDINGS D ESIGNER para conectar la
columna id de la tabla con la propiedad [Link] del
TListView.
2.2 Bases de datos locales y FireDAC
Ahora que hemos satisfecho nuestra lógica curiosidad inicial sobre cómo utilizar
FireDAC en una aplicación propia, con el desarrollo del sencillo ejercicio de la
sección previa, vamos a ocuparnos de aspectos algo más teóricos, comenzando
por las posibilidades que tendremos a nuestro alcance al desarrollar proyectos
que precisan almacenamiento local de datos.
Entendemos por base de datos local aquella que se aloja en el mismo dispo-
sitivo que ejecutará el programa, sea este un ordenador de escritorio o portátil,
una tableta, un teléfono móvil, un smart watch o cualquier otro aparato móvil que
ejecute Windows, OS X, iOS o Android. Esto implica que no es precisa conexión
hacia el exterior a la hora de obtener y manipular los datos, únicamente hay que
abrir un archivo, almacenado en el propio dispositivo, y operar sobre él.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
BASES DE DATOS LOCALES Y FIREDAC 77
Dependiendo de la opción que elijamos, de las que van a describirse en los
siguientes apartados de esta sección, será la propia aplicación la que gestione
el archivo que contiene la información o bien delegará dicha gestión en otro
programa. La elección que hagamos también influirá en otros aspectos, como
los elementos que será necesario distribuir al desplegar el proyecto para ponerlo
en explotación.
Los siguientes apartados describen las opciones que tenemos a nuestro al-
cance usando la versión de FireDAC que se incluye en la edición Professional
de Delphi.
2.2.1 InterBase Lite e InterBase ToGo
InterBase es un RDBMS completo, contemplando aspectos como la definición de
procedimientos almacenados y funciones, el diseño de vistas, la comprobación
de integridad referencial, etc. A pesar de ello no precisa muchos recursos para
su funcionamiento, de ahı́ que existan versiones de este producto capaces de
funcionar en dispositivos móviles.
InterBase Lite e InterBase ToGo son ediciones de este RDBMS pensadas para
su uso embebido, como gestores de bases de datos locales. En ambos casos no se
precisa instalación, solamente hay que redistribuir los archivos apropiados con
nuestra aplicación, y son gestores de datos para un único usuario. La princi-
pal diferencia entre estas dos opciones es que la versión Lite es gratuita, pero
únicamente puede utilizarse sobre bases de datos de tamaño reducido, de 100
megabytes como máximo, y su motor se ejecuta únicamente en un núcleo de
procesamiento. Además solamente se permite una conexión simultánea con la
base de datos.
Las ventajas de InterBase ToGo sobre la versión Lite son múltiples. El tamaño
de la base de datos no está limitada de antemano. A pesar de que también es un
RDBMS monousuario, la aplicación puede tener habilitadas hasta 8 conexio-
nes simultáneas con bases de datos. Además se aprovechan las arquitecturas
multinúcleo con que cuentan actualmente tanto ordenadores como tabletas y
teléfonos móviles, usando hasta 4 núcleos de procesamiento simultáneamente.
Aparte de todas las anteriores, seguramente la diferencia más importante sea que
la edición ToGo nos permite cifrar la base de datos completa tanto con AES
(Advanced Encription Standard) como con DES (Data Encryption Standard),
asegurando ası́ la confidencialidad de la información almacenada en ella.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
78 INTRODUCCIÓN A FIREDAC
NOTA
InterBase Lite e InterBase ToGo pueden ejecutarse sobre Windows, OS X,
iOS y Android. Podemos encontrar más información sobre estas versiones
de InterBase en [Link]
interbase. Las instrucciones sobre cómo obtener la licencia de uso de
InterBase Lite se encuentra en [Link]
ibinstructions. En el capı́tulo 5 aprenderemos más sobre el uso de
InterBase embebido.
Optar desde un principio por InterBase como base de datos local o embebida
facilitarı́a una posterior transición, en caso de que el volumen de información a
almacenar ası́ lo requiriese, a la versión de escritorio o servidor. El formato de
archivo usado por las ediciones Lite y ToGo es el mismo, por lo que el traslado
de la información al nuevo entorno resultarı́a sencillo.
2.2.2 SQLite
Otra opción de tipo embebido y multiplataforma para el almacenamiento de
datos es SQLite, el motor de bases de datos que usábamos en el ejercicio desa-
rrollado en la sección previa. A diferencia de InterBase, SQLite es un producto
de software libre, con el código fuente a disposición pública y que no requiere
ningún tipo de licencia para su uso y redistribución. Esto ha hecho que sea el mo-
tor para operar sobre bases de datos locales con SQL más difundido, contando
con interfaces de acceso desde múltiples lenguajes de programación.
SQLite contempla el uso de múltiples tablas, vistas e ı́ndices, todo ello al-
macenado en un único archivo alojado en el mismo dispositivo que ejecuta la
aplicación. El formato de dicho archivo es multiplataforma, no hay diferen-
cias entre una base de datos SQLite en iOS respecto a Android o en OS X res-
pecto a Windows. Es factible copiar el archivo que contiene la base de datos
de un sistema operativo a otro y utilizarlo sin más. No obstante la mayor ven-
taja de SQLite la encontramos en los mı́nimos recursos que precisa para su fun-
cionamiento, algo que junto al reducido tamaño de la biblioteca hace posible
usar SQLite demandando apenas un megabyte de memoria. Por tanto SQLite es
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
BASES DE DATOS LOCALES Y FIREDAC 79
una solución ideal para dispositivos pequeños y con pocos recursos, como los
wearables.
Además de la portabilidad y reducida exigencia de recursos, SQLite también
ofrece un motor SQL completo, ajustado al estándar SQL92, y contempla el
uso de transacciones, con tolerancia a fallos como caı́das del sistema. No hay
un lı́mite preestablecido en el tamaño de las bases de datos, depende del espacio
disponible y los lı́mites del sistema de archivos, pudiendo alcanzar el orden de los
terabytes. Si el rendimiento es un factor determinante en el proyecto que estemos
desarrollando, SQLite puede operar completamente en memoria mejorando la
velocidad de acceso a los datos respecto a soluciones basadas en archivos y, por
supuesto, aquellas que precisan la comunicación con un servidor.
Entre las limitaciones de SQLite hay que destacar el hecho de que es una
alternativa monousuario, no contemplándose la existencia de usuarios y roles
distintos en una base de datos ni el acceso concurrente a la información. Si bien
es posible extender SQLite mediante su API propia, no existen las funciones y
procedimientos almacenados habituales en los RDBMS.
NOTA
Como pudimos comprobar en el ejercicio desarrollado en la sección pre-
via, es posible trabajar con bases de datos SQLite desde una aplicación
Delphi sin necesidad de instalar software adicional alguno.
2.2.3 Microsoft Access
Access es probablemente la aplicación de gestión de bases de datos de escritorio
más difundida en entornos de tipo SOHO (Small-Office, Home-Office). Se trata
de un producto especı́fico para Windows, por lo que su uso está vinculado a
ordenadores personales. La cantidad de información almacenada a dı́a de hoy
en bases de datos Access es incalculable, razón por la que es probable que en
algún momento precisemos que una aplicación que estemos desarrollando use
dicho formato. Asimismo, el almacenamiento de información en una base de
datos Access abre la puerta a que el usuario pueda acceder a ella por una vı́a
alternativa, con la aplicación Microsoft Access en lugar del programa especı́fico
que se haya desarrollado para dicha tarea.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
80 INTRODUCCIÓN A FIREDAC
Al igual que en los casos anteriores, una base de datos Access se almacena en
un único archivo alojado en el mismo sistema que ejecuta la aplicación. Access
no es un RDBMS, por lo que hay muchas caracterı́sticas habituales de SQL que
no están disponibles. Asimismo cuenta con objetos adicionales que no encon-
traremos en un RDBMS, como son los formularios o los informes, almacenados
también en la base de datos.
El principal inconveniente de las bases de datos Access es que son una solución
limitada a Windows, no siendo posible su uso en OS X, iOS o Android desde
Delphi. Si trabajamos en un proyecto multiplataforma, por tanto, es una alterna-
tiva que descartarı́amos de partida.
NOTA
La actual versión de FireDAC facilita el acceso a bases de datos Access a
través de los controles ODBC de Microsoft, pudiendo utilizarse tanto bases
de datos .mdb como .accdb correspondientes a las versiones 95 a 2010.
La más reciente versión 2013 no está soportada.
2.2.4 Archivos de datos en otros formatos
En ocasiones las necesidades de tratamiento de datos de una aplicación pueden
ser tan simples que incluso una base de datos embebida o de escritorio, como
las citadas en los apartados previos, puede resultar excesivo, siendo suficiente
el almacenamiento directo desde la aplicación a un archivo simple. El formato
de dicho archivo puede ser propietario, pero es recomendable emplear algún
formato estándar como puede ser CSV (Comma Separated Values), XML
(Extensible Markup Language) o DIF (Data Interchange Format).
Cargar en memoria datos guardados en un archivo con cualquiera de esos for-
matos no representa un gran obstáculo, pero una vez completada esta operación
surge la necesidad de operar sobre dichos datos. ¿Cómo efectuar consultas so-
bre información que no está gestionada por un motor SQL? FireDAC facilita
esta tarea gracias a componentes como TFDMemTable y TFDLocalSQL. El
primero actúa como una base de datos en memoria, cuya estructura es posible
definir l ibremente o bien g enerarla a p artir d e a rchivos d e datos existentes. El
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ESTRUCTURA DE UNA APLICACIÓN QUE USA FIREDAC 81
segundo facilita la ejecución de consultas SQL sobre conjuntos de datos que no
están vinculados realmente a una base de datos, como serı́a este caso.
Un proyecto que use esta alternativa será completamente multiplataforma,
ya que únicamente usará archivos de texto que emplean un cierto separador
(CSV/DIF) o unas etiquetas (XML), sin depender de ningún motor de gestión
de datos ni biblioteca externa. El código de los componentes FireDAC se integra
en el propio ejecutable, encargándose de todas las operaciones que necesite la
aplicación. A cambio se renuncia a ciertos beneficios, como la posibilidad de
usar transacciones (soportadas por InterBase Lite/ToGo y SQLite) que garanti-
cen la integridad de los datos, o el hecho de tener a disposición una ruta fácil de
transición a un RDBMS más potente, como ocurre con InterBase.
NOTA
En el capı́tulo 7 aprenderemos a construir una aplicación siguiendo este
enfoque, utilizando solamente componentes FireDAC para gestionar los
datos.
2.3 Estructura de una aplicación
que usa FireDAC
Las aplicaciones Delphi que utilizan componentes FireDAC, siempre circuns-
cribiéndonos a un entorno local, suelen tener una estructura similar, con inde-
pendencia del tipo de base de datos concreta que se utilice. Esta estructura es,
además, la base para aplicaciones cliente/servidor o distribuidas, en las que
simplemente se agregan algunos elementos adicionales. La Figura 2.14 es un
esquema de bloques representando dicha estructura. Distinguimos tres capas:
Interfaz de usuario: Podemos utilizar tanto la biblioteca VCL como la
FMX para diseñar la interfaz de usuario de la aplicación, según nuestras
preferencias y las plataformas objetivo a las que se dirija el proyecto. A lo
largo de este libro utilizaremos preferentemente la FMX, pero la esencia de
los procedimientos a seguir serı́a fundamentalmente la misma con la VCL.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
82 INTRODUCCIÓN A FIREDAC
Figura 2.14 ESTRUCTURA DE UNA APLICACIÓN DELPHI QUE USA FIREDAC PARA
ACCEDER A UNA BASE DE DATOS LOCAL
FireDAC: En esta capa están todos los componentes relativos a gestión de
datos, incluyendo los que conectan con la base de datos (especı́ficos según el
producto con el que vaya a trabajarse), los que actúan como intermediarios
entre la conexión y el almacenamiento local (adaptadores de datos), etc.
Software cliente: En la parte inferior del esquema tenemos las bibliotecas
cliente que se ocupan del acceso fı́sico al archivo que aloja la base de datos,
un software cliente que sı́ es necesario redistribuir con la aplicación como
lo ha sido siempre (usando otras tecnologı́as de acceso a datos de Delphi).
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ESTRUCTURA DE UNA APLICACIÓN QUE USA FIREDAC 83
Todos los componentes FireDAC pasarán a formar parte de la aplicación una
vez se haya compilado, incluyendo los controladores FireDAC para cada base
de datos. Esto representa una diferencia clara respecto a BDE o dbExpress,
bibliotecas que nos obligaban a redistribuir los controladores apropiados a cada
caso. Con FireDAC el código del controlador se integra en nuestro ejecutable.
NOTA
El software cliente de SQLite puede en algunos casos enlazarse
estáticamente en el ejecutable de la aplicación, eliminando la necesidad
de redistribuirlo por separado.
2.3.1 Controladores FireDAC
Los controladores FireDAC para acceso a distintos tipos de orı́genes de datos
los encontraremos en la página F IRE DAC L INKS de la Paleta de herramientas
(véase la Figura 2.15). Concretamente son todos los componentes cuyo nombre
se ajusta al patrón TFDPhysTIPODriverLink, por ejemplo el componente
TFDPhysSQLiteDriverLink que usábamos en el proyecto desarrollado en
la primera sección.
NOTA
La lista de controladores disponibles en la mencionada página
de la Paleta de componentes dependerá de la edición de Delphi
con que estemos trabajando. En la edición Professional no encon-
trarı́amos, por ejemplo, controladores como TFDPhysDB2DriverLink
o TFDPhysOracleDriverLink.
Cuando insertamos uno de esos componentes en un formulario o módulo de
datos de nuestro proyecto, lo que conseguimos es añadir a la cláusula uses del
módulo correspondiente una referencia a un módulo cuyo nombre se ajusta al
patrón [Link], por ejemplo [Link]. Di-
cho módulo contiene el código fuente del controlador FireDAC para una base
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
84 INTRODUCCIÓN A FIREDAC
Figura 2.15 COMPONENTES PARA ENLAZAR LOS CONTROLADORES EN EL PROYECTO
de datos concreta. De hecho, una vez se ha añadido la mencionada referencia
podrı́amos eliminar el componente y el proyecto compiları́a y funcionarı́a igual-
mente. Estos componentes son sencillamente un atajo que nos ahorran agregar
la referencia manualmente.
Entre los controladores FireDAC podemos encontrar dos que actúan a modo
de puente o pasarela, facilitando el acceso a cualquier origen de datos ODBC
(TFDPhysODBCDriverLink) o bien usar cualquier controlador dbExpress
(TFDPhysTDBXDriverLink). De esta forma se amplia la cantidad de bases
de datos a las que es posible acceder desde una aplicación Delphi mediante
FireDAC.
Los servicios ofrecidos por el controlador que hayamos elegido permitirán
al componente TFDConnection establecer conexión con el software cliente
de la base de datos, ya sea directamente o bien a través de una infraestructura
de red cuando se trabaja con un servidor. Habilitada la conexión la aplicación
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ESTRUCTURA DE UNA APLICACIÓN QUE USA FIREDAC 85
podrá recuperar conjuntos de datos, ası́ como ejecutar otro tipo de sentencias
SQL, siempre según las caracterı́sticas de la base de datos con la que se esté
trabajando.
2.3.2 Conjuntos de datos
Disponiendo de una conexión a la base de datos, en una capa que estarı́a justo
por encima de la formada por los controladores FireDAC y el componente de
conexión, encontramos los componentes que representan conjuntos de datos. La
clase base para conjuntos de datos FireDAC es TFDDataSet, derivada de la
clase genérica TDataSet4 . De TFDDataSet derivan, entre otras, tres clases
que corresponden a los tres componentes fundamentales que usaremos al trabajar
con FireDAC:
TFDTable: Representa un conjunto de datos obtenido a partir del con-
tenido de una tabla de la base de datos. Cuenta con la funcionalidad nece-
saria para introducir cambios en los datos y trasladarlos a la base de datos.
TFDQuery: Mediante este componente es posible ejecutar cualquier con-
sulta SQL, obteniendo un conjunto de resultados que puede proceder de
múltiples tablas. Al igual que el anterior cuenta con las funciones nece-
sarias para manipular los datos y transferir los cambios a la base de datos.
TFDMemTable: Este componente hace posible trabajar con un conjunto de
datos alojado en memoria, siendo opcional el uso de la conexión a la base
de datos para obtener información o comunicar cambios.
NOTA
Encontraremos los tres componentes previos en la página F IRE DAC de
la Paleta de componentes.
4
TDataSet es una clase que actúa como conjunto de datos genérico, siendo
la base de los conjuntos de datos de IBX (TIBCustomDataSet), de dbExpress
(TCustomSQLDataSet), etc.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
86 INTRODUCCIÓN A FIREDAC
Las tres clases anteriores están derivadas de TFDAdaptedDataSet. Esta
clase implementa las funciones que hacen posible la ejecución de consultas, ob-
tención de datos y envı́o de cambios a orı́genes heterogéneos, usando para ello
el adaptador apropiado. Esta es una funcionalidad que, por tanto, heredan los
citados componentes.
Además de para trabajar con conjuntos de datos, en la página F IRE DAC
también encontraremos componentes cuya finalidad es facilitar la ejecución de
consultas SQL en general (TFDCommand), la gestión de transacciones cuando
se opera con un RDBMS (TFDTransaction), la ejecución de procedimientos
almacenados (TFDStoredProc), etc.
2.3.3 Elementos de interfaz
Además de componentes no visibles cuya finalidad es encargarse de la gestión
de conexiones y datos, como todos los citados hasta ahora, FireDAC también
cuenta con algunos controles con una parte visual (véase la Figura 2.16). Estos
elementos pasan a formar parte de la interfaz de usuario de la aplicación, por
ejemplo a fin de poder solicitar las credenciales de conexión a una base de datos
o indicar visualmente que hay una tarea en espera de ser completada.
Figura 2.16 C OMPONENTES F IRE DAC ASOCIADOS A ELEMENTOS DE LA INTERFAZ DE
USUARIO .
El único componente de este tipo que obligatoriamente hemos de agregar a
nuestros proyectos es TFDGUIxWaitCursor. Este es usado por FireDAC para
mostrar un cursor de espera.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ESTRUCTURA DE UNA APLICACIÓN QUE USA FIREDAC 87
Todos los componentes de este grupo cuentan con tres implementaciones dis-
tintas, recurriéndose a una u otra según que nuestra aplicación use la FMX, la
VCL o sea una aplicación de consola. La propiedad Provider permite
cambiar el tipo, tal y como se muestra en la Figura 2.17. Este cambio afectarı́a a
todos los componentes de interfaz de FireDAC.
Figura 2.17 SELECCI ÓN DEL PROVEEDOR DE INTERFAZ DE USUARIO
Al igual que ocurrı́a con los controladores FireDAC, estos componentes lo
que hacen es agregar una referencia al módulo adecuado en la cláusula uses de
nuestro formulario o módulo de datos. Tras esta operación podrı́amos eliminar-
los sin ningún problema.
2.3.4 Otros componentes FireDAC
A pesar de que FireDAC es una solución universal de acceso a datos, permitién-
donos usar los mismos componentes sobre distintos tipos de bases de datos,
también incorpora componentes más especı́ficos, diseñados para aprovechar las
ventajas de productos concretos. Encontramos dichos componentes en la página
F IRE DAC S ERVICES de la Paleta de componentes.
La nomenclatura de estos componentes nos indica tanto el tipo de base de
datos sobre la que operan como el tipo de servicio que ofrecen. Ası́, mediante el
componente TFDSQLiteBackup es posible realizar una copia de seguridad de
una base de datos SQLite y restaurarla, con el componente TFDIBConfig se
facilita el acceso a los parámetros de configuración de bases de datos InterBase, y
con el componente TFDMSAccessService las funciones de compactación y
reparación de bases de datos Access podrı́an llevarse a cabo desde una aplicación
Delphi.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
88 INTRODUCCIÓN A FIREDAC
2.4 Resumen
Al finalizar este capı́tulo, en el que se ha desarrollado un proyecto básico con
FireDAC y se ha hecho un recorrido posterior por la estructura de una aplicación
que use dichos componentes, tenemos una visión general de lo que nos ofrece
esta tecnologı́a de acceso a datos. Nos hemos concentrado sobre todo en los
servicios relacionados con el trabajo con orı́genes de datos locales, pero la arqui-
tectura fundamental serı́a la misma en un contexto cliente/servidor o distribuido.
Con este conocimiento de FireDAC, por ahora relativamente superficial, esta-
mos en disposición de comenzar a profundizar en aspectos cada vez más concre-
tos. Ese será el objetivo de capı́tulos posteriores. Antes, sin embargo, es nece-
sario que conozcamos las herramientas indispensables para trabajo con bases de
datos con que cuenta el entorno de Delphi. Este será el objetivo del capı́tulo
siguiente.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Capı́tulo 3
HERRAMIENTAS DEL
ENTORNO DE DELPHI PARA
TRABAJAR CON BASES DE
DATOS
Como bien sabemos Delphi es un entorno de desarrollo de tipo RAD (Rapid
Application Development), lo cual significa que muchas de las tareas que es
necesario llevar a cabo durante la creación de un proyecto pueden ser
completadas visualmente, ya sea mediante herramientas integradas en el entorno
o arrastrando y soltando componentes que después son personalizados mediante
la modificación de sus propiedades.
El IDE de Delphi cuenta con varias utilidades que facilitarán nuestro trabajo a
la hora de conectar nuestra aplicación con bases de datos. El objetivo de este
capıtulo es que nos familiaricemos con esas herramientas, a fin de que seamos
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
90 HERRAMIENTAS BDD EN DELPHI
capaces de aprovecharlas lo mejor posible en los capı́tulos siguientes, cuando
abordemos el diseño de proyectos concretos. Algunas de estas herramientas,
como los módulos de datos o el Explorador de datos, ya los hemos usado en el
capı́tulo previo.
3.1 Módulos de datos
Cuando se comienza a trabajar en el desarrollo de una aplicación Delphi que va
a conectar a bases de datos es bastante habitual, incluso por parte de usuarios
ya experimentados en la creación de proyectos con Delphi, el ir agregando al
formulario en el que se trabaja los componentes de conexión a datos a medida
que van necesitándose. Esta costumbre no es recomendable ya que, por regla
general, tarde o temprano nos llevará a agregar los mismos componentes con la
misma configuración a otros formularios en los que también se precise la misma
información.
Más allá del hecho de duplicar componentes y configuración, lo cual de por
sı́ ya puede complicar la posterior fase de mantenimiento en caso de que hubiese
que aplicar cambios en los parámetros de conexión a la base de datos, sin duda el
mayor inconveniente es que también se duplicará código relacionado exclusiva-
mente con la gestión de datos. A largo plazo esto será una fuente de problemas,
especialmente si la persona que ha de mantener el proyecto no es la misma que
lo desarrolló.
Para evitarlo existen los módulos de datos, un tipo de contenedor que uti-
lizábamos en el ejercicio propuesto en el capı́tulo previo. Un mismo proyecto
puede contar con tantos módulos de datos como se precisen. Habitualmente sólo
usarı́amos uno, pero si el proyecto lo requiere, porque conecte con múltiples
bases de datos, podrı́a ser recomendable emplear varios.
Los módulos de datos son clases derivadas del tipo TDataModule que, a
su vez, es un descendiente directo de la clase TComponent, raı́z de todos
los componentes Delphi. Un módulo de datos, por tanto, es idéntico en una
aplicación basada en la VCL que en otra que use la FMX, razón por la que
únicamente puede alojar componentes no visuales, como son los que forman
parte de FireDAC.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
DATA EXPLORER 91
Centralizar los componentes FireDAC y todo el código asociado en un módulo
de datos es una inversión que realizamos durante el desarrollo inicial cuyos fru-
tos obtendremos en el futuro, siempre que tengamos que realizar cualquier tipo
de actualización o cambio, ya que estaremos completamente seguros de que so-
lamente hay un punto a revisar: el contenido del módulo de datos.
3.2 Data Explorer
El Explorador de datos (ventana DATA E XPLORER) lo usábamos en el capı́tulo
previo para acceder a la base de datos SQLite de ejemplo, examinando y modifi-
cando su contenido. En su interior encontraremos dos nodos principales llama-
dos F IRE DAC y DB E XPRESS, cada uno de los cuales contendrá tantos subno-
dos como controladores haya disponibles. El nodo de cada controlador puede
estar vacı́o, si no hay definida ninguna conexión que lo use, o bien dar paso a
tantas entradas como conexiones haya definidas. Estas entradas son, en último
término, las que realmente nos interesarán.
NOTA
La lista de conexiones mostrada por el Explorador de datos es el reflejo
de la información almacenada en un archivo de definiciones global, gene-
rado durante la instalación de Delphi. Habitualmente lo encontraremos en
C:\RAD Studio\FireDAC.
En esta sección van a describirse los procedimientos a seguir para definir una
nueva conexión, explorar conexiones existentes y usarlas para agregar al módulo
de datos los componentes de conexión necesarios.
3.2.1 Definición de conexiones
Salvo que vayamos a utilizar alguna de las conexiones asociadas a bases de datos
de ejemplo para realizar alguna prueba, normalmente lo primero que haremos
será definir una nueva conexión a fin de poder acceder a la información asociada
a nuestro proyecto. Los pasos a seguir para ello son los indicados a continuación:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
92 HERRAMIENTAS BDD EN DELPHI
1. Seleccionamos el nodo correspondiente al controlador FireDAC apropiado
a fin de que la nueva conexión tome sus parámetros por defecto.
2. Abrimos el menú contextual de dicho nodo y elegimos la única opción que
hay disponible (véase la Figura 3.1).
Figura 3.1 AGREGAMOS UNA NUEVA CONEXI ÓN ASOCIADA AL CONTROLADOR DE
INTERBASE
3. En el pequeño cuadro de diálogo que se abre a continuación debemos in-
troducir el nombre que queremos asignarle a la nueva conexión. No pueden
existir dos conexiones con el mismo nombre, por lo que este ha de ser único.
4. Hacemos clic en OK para acceder a la ventana F IRE DAC C ONNECTION
E DITOR. Esta es la misma que usamos en el capı́tulo previo. Dependiendo
del tipo de controlador seleccionado, la lista de parámetros de la lista infe-
rior cambiará.
Además de los parámetros de conexión, tales como la ruta a la base de datos,
el nombre de usuario y contraseña si son necesarios o la codificación de carac-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
DATA EXPLORER 93
teres a usar, en la página O PTIONS de esta ventana, mostrada en la Figura 3.2,
encontramos una extensa lista de opciones de configuración. Con ellas es posible
establecer conversiones de tipos de datos entre la base de datos y la aplicación,
determinar la manera en que se tratarán las cadenas de caracteres, cómo se ges-
tionarán los bloqueos o las relaciones maestro/detalle, etc.
Figura 3.2 OPCIONES DE CONFIGURACI ÓN DE LA CONEXI ÓN
Una vez que hayamos introducido toda la información necesaria podemos
cerrar la ventana, guardando los parámetros de conexión en el archivo global
anteriormente citado. Antes, si lo deseamos, podemos usar el botón T EST de la
página D EFINITION para comprobar si la conexión es posible.
Mediante las opciones del menú contextual de una conexión ya existente
podemos cambiar su nombre, acceder a esta misma ventana para cambiar su
configuración o eliminarla.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
94 HERRAMIENTAS BDD EN DELPHI
3.2.2 Exploración de datos
Disponiendo de una conexión ya definida, podemos usar el Explorador de datos
para aquello que denota su nombre: explorar la estructura de la base de datos.
Al hacer clic en el botón + que hay a la izquierda de la conexión se procederá
a conectar, solicitándonos las credenciales si fuese necesario. En caso de que se
trate de un RDBMS remoto, ejecutándose en una máquina distinta a la de
desarrollo, lógicamente deberemos contar con conectividad y privilegios de
acceso al servidor.
Los nodos de primer nivel de una conexión corresponden a categorías de ob-
jetos que pueden existir en la base de datos: tablas, vistas, ı́ndices,
procedimientos almacenados, etc. Según el tipo de objeto tendremos a nuestra
disposiciónn unas opciones u otras. Las tablas y vistas cuentan con la opción
VIEW (véase la Figura 3.3), cuya finalidad es mostrarnos los datos que
contienen. Además también podemos examinar la lista de columnas de las
tablas, los índices que tienen asociados, las claves primarias y foráneas, etc.
Figura 3.3 EXPLORACI ÓN DE LA ESTRUCTURA DE UNA BASE DE DATOS
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
DATA EXPLORER 95
El uso interactivo de la base de datos que nos permite llevar a cabo el Ex-
plorador de datos es sencillamente un atajo, gracias al cual podemos saber qué
parámetros precisa un procedimiento almacenado o cómo se llaman las colum-
nas de una tabla sin necesidad de recurrir a la interfaz de usuario propia de
cada RDBMS o base de datos. No tenemos, por ejemplo, que abrir el SQL
S ERVER M ANAGEMENT S TUDIO para realizar dichas tareas, todo el trabajo se
desempeña desde el propio entorno de Delphi.
3.2.3 Inserción de componentes de conexión
Una de las tareas iniciales a la hora de desarrollar un proyecto con conexión a
datos es la inserción, en el módulo de datos, de los componentes de conexión y
los componentes de consulta para recuperar la información. Esta es una tarea en
la que el Explorador de datos puede ahorrarnos un trabajo considerable, evitando
que todo el trabajo de configuración que hemos hecho al definir la conexión
tengamos que repetirlo nuevamente al configurar un TFDConnection.
Tomando cualquier tabla o vista desde el Explorador de datos y arrastrándola
hasta el módulo de datos1 conseguiremos que se inserten automáticamente un
TFDConnection2 y un TFDQuery, ambos apropiadamnete configurados para
acceder a los datos de la tabla o vista. También podemos arrastrar y soltar un
procedimiento almacenado, en cuyo caso el segundo componente agregado serı́a
un TFDStoredProc en lugar de un TFDQuery.
Al configurar un componente TFDConnection manualmente, tal y como
se describió en el capı́tulo previo, los parámetros que determinan el controlador
FireDAC a usar, la localización de la base de datos, etc., se almacenan en el pro-
pio componente. Esto implica que al compilar el proyecto estamos introduciendo
en el ejecutable toda esa información, por lo que no será posible modificarla
salvo que introduzcamos en la aplicación alguna función con tal fin.
Cuando el componente TFDConnection se ha añadido mediante arrastrar
y soltar, como se ha hecho en la Figura 3.4, la configuración es distinta. Los
datos de conexión no están en la propiedad Params del componente, sino en el
archivo de parámetros FireDAC global. Es la propiedad ConnectionDefName
1
También se podrı́a arrastrar directamente a un formulario.
2
Si ya existiese un componente de conexión a esa base de datos serı́a reutilizado, en lugar
de agregar otro nuevo.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
96 HERRAMIENTAS BDD EN DELPHI
de TFDConnection la que contiene el nombre de la conexión predefinida a
usar, de forma que durante la ejecución se buscará el citado archivo de configu-
ración, se localizará en él la conexión indicada (de ahı́ que su nombre deba ser
único) y se cargarán los parámetros de configuración. Esto permite que dichos
parámetros sea modificados externamente a la aplicación, simplemente editando
el archivo [Link] correspondiente.
Figura 3.4 COMPONENTES AGREGADOS MEDIANTE ARRASTRAR Y SOLTAR
NOTA
Lógicamente el archivo global de configuración de FireDAC, instalado
junto a Delphi y gestionado por el Explorador de datos, no estará disponible
en los equipos en los que vaya a ponerse en explotación la aplicación.
En la sección siguiente conoceremos una herramienta especı́fica cuya finali-
dad es editar el contenido de archivos de definición de conexiones FireDAC, ya
sea el de configuración global o módulos de definición asociados a proyectos
concretos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
FIREDAC EXPLORER 97
3.3 FireDAC Explorer
En el menú T OOLS de Delphi encontraremos una opción que abre el programa
F IRE DAC E XPLORER. Esta utilidad es una herramienta genérica para la ma-
nipulación de parámetros de conexión de FireDAC almacenados en archivos de
definición de conexiones. Por defecto, cuando iniciamos el programa, se abre
el archivo de definiciones global de FireDAC. Usando los dos primeros botones
que hay en la barra de herramientas (véase la Figura 3.5), sin embargo, podemos
tanto crear nuevos archivos como abrir otros, según nuestras necesidades.
Figura 3.5 FIREDAC EXPLORER
El árbol mostrado en el panel izquierdo se asemeja al contenido del Explo-
rador de datos, ya que contiene una lista de controladores FireDAC y conexiones
asociadas a los mismos. Con el menú de opciones contextual podemos definir
nuevas conexiones, ası́ como manipular las ya existentes. Abriendo una conexión
y seleccionando los objetos que contiene la base de datos, por ejemplo tablas y
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
98 HERRAMIENTAS BDD EN DELPHI
vistas, obtendremos en el panel derecho información sobre su estructura, ası́
como acceso a su contenido. Este panel cuenta con funciones que nos permiten
agrupar los datos, filtrarlos, ordenarlos, etc. En la Figura 3.6, por ejemplo, se
han agrupado los pedidos de una base de datos por el código de cliente a que
pertenecen.
Figura 3.6 ES POSIBLE CREAR GRUPOS, ORDENAR Y FILTRAR LOS DATOS
Asimismo podemos crear scripts SQL, con la opción N EW SQL S CRIPT,
preparando y probando las consultas que posteriormente utilizarı́amos en el pro-
yecto. Al crear un nuevo guión SQL se abrirá un panel de edición simple, conec-
tado a la base de datos que tuviésemos seleccionada en el panel izquierdo, per-
mitiéndonos operar de manera interactiva. Estos guiones SQL podemos guardar-
los y, posteriormente, recuperarlos para su uso, por ejemplo en un componente
TFDQuery.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
FIREDAC EXPLORER 99
NOTA
Si tenemos en el sistema alias BDE de proyectos anteriores, desde
FireDAC Explorer podemos importar esas definiciones a fin de acceder a las
mismas bases de datos usando componentes FireDAC. Para ello usarı́amos
la opción C ONNECTION —I MPORT BDE A LIASES, seleccionando a con-
tinuación los alias BDE que deseemos importar.
3.3.1 Archivos de definición de conexiones
locales a un proyecto
Como se apuntaba anteriormente, el archivo en el que se alojan las definiciones
de conexión FireDAC en nuestro equipo de desarrollo no estará disponible en
los equipos en los que, finalmente, se despliegue la aplicación. Si los
componentes TFDConnection usados en esta apuntan, mediante su
propiedad ConnectionDefName, a dichas definiciones el programa no podrá
funcionar al no encontrarlas.
La solución es simple: incorporar al proyecto un archivo de definición de
conexiones local, a medida para la aplicación. Los pasos a seguir para ello son
los siguientes:
1. Mediante la opción T OOLS —F IRE DAC E XPLORER del menú principal
de Delphi abrimos el FireDAC Explorer.
2. Hacemos clic en el botón N EW C ONN D EF F ILE y seleccionamos la car-
peta en la que se alojará el nuevo archivo. Dicha carpeta serı́a la que vaya a
alojar el ejecutable de nuestro proyecto.
3. Usando las opciones del panel izquierdo creamos las conexiones que nece-
sitemos y comprobamos su funcionamiento. En las rutas a bases de datos
deberı́amos utilizar siempre caminos relativos, no absolutos que hagan re-
ferencia a las unidades y estructura de directorios de nuestro equipo de de-
sarrollo.
4. Cerramos el FireDAC Explorer. A partir de ahora, al ejecutar la aplicación
esta encontrará el archivo local de definiciones y usará su contenido.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
100 HERRAMIENTAS BDD EN DELPHI
Siempre que incluyamos el archivo de definición de conexiones en el proceso
de despliegue, situándolo en la carpeta donde esté el ejecutable, y la propiedad
ConnectionDefName del componente TFDConnection coincida con el
nombre de las definiciones alojadas en dicho archivo, nuestra aplicación podrá
conectar con las bases de datos que precisa.
NOTA
Por convención, el archivo de definición de conexiones FireDAC siempre
tendrá por nombre [Link].
3.3.2 Estructura de un archivo de definición
de conexiones FireDAC
Si al desplegar la aplicación necesitásemos efectuar cambios en la definición
de alguna conexión, y no dispusiésemos de la anterior herramienta, podemos
recurrir a cualquier editor de texto básico. Al fin y al cabo no es más que un
archivo de texto con una estructura muy básica, como la de cualquier archivo de
tipo INI.
Cada entrada viene denotada por una cabecera [NombreConexión]. Tras
ella, cada lı́nea contendrá una pareja clave=valor estableciendo los distintos
parámetros de la conexión.
En el listado siguiente se muestra el contenido de un archivo de definición
FireDAC con dos conexiones. La primera es una base de datos InterBase de
ejemplo, mientras que la segunda corresponde a la base de datos creada como
ejercicio en el capı́tulo previo. Observa cómo el parámetro Database de esta
última usa una ruta relativa para hacer referencia a la base de datos.
1 [[Link]]
2 Encoding=UTF8
3
4 [EMPLOYEE]
5 DriverID=IB
6 Protocol=TCPIP
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
FIREDAC MONITOR 101
7 Database=localhost:C:\ProgramData\Embarcadero\InterBase\⤦
Ç gds_db\examples\database\[Link]
8 User_Name=sysdba
9 Password=masterkey
10 CharacterSet=
11 ExtendedMetadata=True
12
13 [HolaFireDAC]
14 Database=..\HolaFireDAC\[Link]
15 DriverID=SQLite
Listado 3.1 Archivo [Link]
3.4 FireDAC Monitor
En el menú T OOLS encontramos una segunda opción, con el tı́tulo F IRE DAC
M ONITOR, que da acceso a otra de las herramientas de FireDAC. El objetivo
de esta es inspeccionar toda la comunicación entre una aplicación que utiliza
componentes FireDAC y la base de datos. Se trata, por tanto, de una utilidad de
asistencia tanto a la depuración como al análisis del rendimiento.
Realmente podemos generar un registro de toda la actividad de los compo-
nentes FireDAC usados en la aplicación sin necesidad de usar la anterior
herramienta, dirigiendo la salida a un archivo de registro (log) o bien con una
configuración a medida. Con el FireDAC Monitor, no obstante, ya tenemos lo
necesario para inspeccionar dicha actividad de forma interactiva.
3.4.1 Componentes de supervisión FireDAC
En la Paleta de herramientas, concretamente en la página F IRE DAC L INKS,
encontrarás tres componentes relacionados con la monitorización de FireDAC.
Cada uno de ellos envı́a los eventos registrados a un destino distinto:
TFDMoniCustomClientLink: Envı́a el flujo de eventos a un gestor que
habrı́amos de implementar nosotros, respondiendo al evento OnOutput.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
102 HERRAMIENTAS BDD EN DELPHI
En el método asociado a dicho evento procesarı́amos la información de re-
gistro como nos conviniese, lo cual nos permite un tratamiento totalmente
personalizado.
TFDMoniFlatFileClientLink: Almacena la información de los even-
tos generados por FireDAC en un archivo de texto simple. Al finalizar el
proceso el componente muestra la lista de archivos de traza.
TFDMoniRemoteClientLink: Transmite toda la información de los
eventos producidos por FireDAC a la herramienta FireDAC Monitor. Esta
debe estar en ejecución antes de comenzar el proceso de trazado.
Cada uno de estos tres componentes cuenta con un conjunto de propiedades
que facilita su configuración, por ejemplo determinando el puerto TCP/IP en
el que un TFDMoniRemoteClientLink buscará la utilidad FireDAC Moni-
tor, o estableciendo la ruta y el nombre del archivo en el que el componente
TFDMoniFlatFileClientLink escribirá el registro.
Figura 3.7 CONFIGURACI ÓN DE SUPERVISI ÓN EN EL COMPONENTE TFDCO N N E C T I O N
Además de incluir el componente apropiado en nuestro módulo de datos,
también tendremos que especificar en el componente TFDConnection el tipo
de supervisión que se desea utilizar3 . Para ello tendremos que modificar la
3
En un mismo módulo de datos podemos tener varios TFDConnection y múltiples
componentes de supervisión, estableciéndose de esta forma qué método usará cada conexión.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
FIREDAC MONITOR 103
propiedad MonitorBy, seleccionando uno de los cuatro valores disponibles
(véase la Figura 3.7). Finalizada esta configuración estarı́amos en disposición
de comenzar a inspeccionar la actividad de FireDAC durante la ejecución del
programa.
3.4.2 La interfaz de FireDAC Monitor
Esta utilidad tiene una interfaz de usuario extremadamente sencilla. Como puede
apreciarse en la Figura 3.8, la parte superior está ocupada por una barra de
herramientas que facilita las operaciones más comunes: borrar la lista de
eventos, guardarla, pausar/reanudar el registro de eventos y mantener la ventana
en primer plano.
Figura 3.8 INTERFAZ DE USUARIO DEL PROGRAMA FIREDAC MONITOR
La parte central de la interfaz cuenta con dos paneles. El superior muestra
una lista con cada uno de los eventos recibidos de la aplicación que está super-
visándose, incluyendo una marca de tiempo y un resumen abreviado. En el panel
inferior se facilitan detalles sobre el evento seleccionado en la lista anterior.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
104 HERRAMIENTAS BDD EN DELPHI
3.5 Herramientas asociadas a
componentes FireDAC
Como ya sabemos, el componente TFDConnection tiene asociado un editor
de configuración especı́fico, accesible desde su menú contextual o simplemente
haciendo doble clic sobre él. Este no es el único componente FireDAC que
cuenta con herramientas a medida.
En el menú contextual de un TFDStoredProc encontraremos las opciones
E XECUTE y N EXT RECORD SET, en el de un TFDTable también se ofrece la
opción F IELDS E DITOR y en el de un TFDQuery se agrega la opción Q UERY
E DITOR (véase la Figura 3.9). Cada una de ellas ejecuta una función o da paso
a una utilidad independiente, actuando siempre sobre el conjunto de datos vin-
culado al componente.
Figura 3.9 OPCIONES ASOCIADAS AL COMPONENTE TFDQU E R Y
3.5.1 El Editor de campos
Los componentes TFDTable y TFDQuery se utilizan para obtener información
de la base de datos. Dicha información está estructurada en columnas, cada una
de las cuales tiene un nombre, un tipo de dato y, posiblemente, restricciones y
otros atributos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HERRAMIENTAS ASOCIADAS A COMPONENTES FIREDAC 105
Si examinamos el contenido de un componente TFDQuery en la ventana
S TRUCTURE (en segundo plano en la Figura 3.10), comprobaremos que exis-
ten varias ramas inicialmente vacı́as. Estas se corresponden con las propiedades
Aggregates, Constraints, Fields, Indexes, Macros y Params del
componente, todas ellas colecciones que almacenan información sobre campos
agregados, restricciones, columnas, ı́ndices, macros y parámetros, respectiva-
mente. La colección Fields tiene asociado un editor especı́fico (en primer
plano en la misma Figura 3.10), el Editor de campos, al que da paso la opción
F IELDS E DITOR antes mencionada.
Figura 3.10 EL EDITOR DE CAMPOS Y SU MEN Ú CONTEXTUAL
Salvo que establezcamos lo contrario, el contenido de las anteriores cole-
cciones se determinará automáticamente durante la ejecución de la aplicación,
una vez que se conecte con la base de datos y el componente TFDTable o
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
106 HERRAMIENTAS BDD EN DELPHI
TFDQuery pueda obtener toda la información de definición d e l as columnas,
ı́ndices, etc. Por cada columna se generará un objeto de clase TField, confi-
gurado a través de sus propiedades y posteriormente almacenado en la colección
Fields.
Al abrir el Editor de campos lo encontraremos inicialmente vacı́o. Esto
implica que la información de las columnas se obtendrá dinámicamente, durante
la ejecución. Mediante la opción ADD FIELD del menú contextual accederemos a
una ventana con la lista completa de columnas correspondientes a la tabla o con-
sulta, pudiendo seleccionar aquellas que queremos tener disponibles. También
podemos usar la opción A DD ALL FIELDS para agregarlas todas. Lo que con-
seguimos con esto es definir el contenido de la colección Fields en la fase de
diseño, estableciendo la configuración de cada campo de manera estática.
Figura 3.11 PROPIEDADES DE UN OBJETO TFI E L D EN EL INSPECTOR DE OBJETOS
Usando el Inspector de objetos (véase la Figura 3.11) podemos personalizar la
configuración de cada T Field, modificando los valores establecidos au-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HERRAMIENTAS ASOCIADAS A COMPONENTES FIREDAC 107
tomáticamente a partir de la información obtenida de la base de datos. Podrı́amos,
por ejemplo, introducir una expresión en la propiedad CustomContrainst
para definir una restricción a medida que precise nuestra aplicación.
NOTA
Al definir en la fase de diseño los campos que ha de tener un conjunto de
datos, agregándolos a la colección Fields, estamos fijando su estructura
respecto a cómo estaba la base de datos durante el desarrollo. Si hubiese
algún cambio posterior en ella, la aplicación detectarı́a la inconsistencia
de manera inmediata al ejecutarse.
Adición de campos calculados
Una de las tareas para las que suele utilizarse el Editor de campos es la definición
de campos calculados a un conjunto de datos. Para ello se utiliza la opción N EW
FIELD de su menú contextual. Esta da paso al cuadro de diálogo mostrado en la
Figura 3.12.
Figura 3.12 DEFINICI ÓN DEL NUEVO CAMPO AGREGADO AL CONJUNTO DE DATOS
Además de establecer el nombre que tendrá la nueva columna en el conjunto
de datos, ası́ como el nombre del componente, debemos especificar e l t ipo de
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
108 HERRAMIENTAS BDD EN DELPHI
campo eligiendo entre las cinco posibilidades ofrecidas en el apartado F IELD
TYPE . Con la opción C ALCULATED indicarı́amos que se tratará de una columna
calculada, cuyo contenido se establecerá en ejecución en respuesta al evento
OnCalcFields del componente TFDTable o TFDQuery que contiene el
campo.
3.5.2 El Editor de consultas
Otra de las herramientas relacionadas con la gestión de datos que encontramos
en el menú contextual de ciertos componentes FireDAC es el Editor de consultas
(véase la Figura 3.13). Como su propio nombre denota, su finalidad es facilitar
la composición de consultas SQL, permitiendo probarlas de formar interactiva y
pudiendo usar parámetros sustituibles.
Figura 3.13 EL EDITOR DE CONSULTAS NOS PERMITE PROBAR LAS SENTENCIAS SQL
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HERRAMIENTAS ASOCIADAS A COMPONENTES FIREDAC 109
La página SQL C OMMAND de esta herramienta será la que utilicemos con
más frecuencia. En ella aparecerá la sentencia SQL que está utilizándose ac-
tualmente. Si hemos obtenido el componente al arrastrar una tabla desde el
Explorador de datos, dicha consulta será tan simple como el clásico (y nada
recomendable) SELECT * FROM tabla. Modificando la consulta podremos
seleccionar las columnas que realmente necesitamos en la aplicación, filtrar las
filas, establecer su orden, si fuese necesario agrupar los datos, etc. Cada vez
que modifiquemos la consulta no tenemos más que hacer clic en E XECUTE para
ejecutarla, obteniendo en la parte inferior el conjunto de datos resultante e infor-
mación sobre su estructura.
En una consulta SQL pueden utilizarse parámetros sustituibles. Estos repre-
sentan un valor que se usarı́a en algún punto de la consulta pero que no es cono-
cido en el momento de escribir esta, debiendo facilitarse con posterioridad, nor-
malmente durante la ejecución. La mostrada en el Listado 3.2 es un ejemplo de
este tipo de consulta. El parámetro se ha utilizado en la cláusula WHERE y se
llama RefDate. Al colocar dos puntos delante del nombre estamos indicando
que se trata de un parámetro sustituible.
1 SELECT Company, City, Country, Contact, LastInvoiceDate
2 FROM customer
3 WHERE LastInvoiceDate > :RefDate
4 ORDER BY Country, LastInvoiceDate DESC
Listado 3.2 Consulta con parámetros sustituibles
La página PARAMS del Editor de consultas nos servirá para configurar los
parámetros sustituibles, estableciendo su tipo, tamaño y el valor que le quere-
mos dar para probar la consulta. En la Figura 3.14 se muestra la configuración
asociada al parámetro RefDate de la consulta de ejemplo previa, indicando que
su tipo es ftDate y que su valor inicial será 01/01/1995.
Para facilitar en ejecución el valor que se desea asignar a un parámetro susti-
tuible podemos utilizar la propiedad Params del TFDQuery o bien recurrir al
método ParamByName. Ambos miembros los encontraremos documentados en
la ayuda electrónica de Delphi. Posteriormente aprenderemos a usar este último
en un ejercicio práctico.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
110 HERRAMIENTAS BDD EN DELPHI
Figura 3.14 CONFIGURACI ÓN DE PAR ÁMETROS USADOS EN LA CONSULTA
3.6 El asistente de Live Bindings
La última herramienta de la que vamos a ocuparnos en este capı́tulo es el asis-
tente L IVE B INDINGS W IZARD. Este se abre mediante el último de los botones
que hay en la barra lateral del L IVE B INDINGS D ESIGNER, el panel de enlace
visual entre datos y controles de la interfaz de usuario que abrı́amos con la opción
B IND V ISUALLY del menú contextual de cualquier control.
Este asistente cuenta con un número variable de pasos, dependiendo de la
acción que elijamos en la primera página. Como se aprecia en la Figura 3.15 las
opciones disponibles son cinco. La última nos permite crear un nuevo conjunto
de datos (un componente TFDTable o TFDQuery), facilitando la selección
de una conexión o un controlador y agregando al contenedor actual los compo-
nentes necesarios. Las otras cuatro opciones tienen por finalidad c onectar un
control de interfaz de usuario con un campo de un conjunto de datos o una de las
propiedades de un componente.
El procedimiento para conectar un control a un campo de la base de datos, o
una cuadrı́cula con un conjunto de campos, es fundamentalmente el mismo. En el
primer caso tendrı́amos que seleccionar el tipo de control que queremos utilizar
para mostrar la información del campo, mientras que en el segundo se usarı́a un
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EN LA PRÁCTICA 111
Figura 3.15 ASISTENTE PARA LIVE BINDINGS
componente TGrid o equivalente. A partir de aquı́ podrı́amos seleccionar uno
de los conjuntos de datos ya existentes, por ejemplo agregados antes al módulo
de datos, o bien optar porque el asistente los genere también.
Al finalizar el asistente tendrı́amos en el formulario todos los componentes y
controles necesarios, con los vı́nculos entre ellos adecuadamente establecidos lo
cual nos ahorra una cantidad considerable de tiempo.
3.7 En la práctica
Terminamos poniendo en práctica el uso de muchas de las herramientas descritas
en las secciones de este capı́tulo. Para ello desarrollaremos una sencilla apli-
cación cuya finalidad será mostrar datos de una tabla de una de las bases de datos
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
112 HERRAMIENTAS BDD EN DELPHI
de ejemplo distribuidas con Delphi, facilitando también su edición. Además el
programa permitirá establecer un filtro a la información mostrada, añadiendo
también una columna cuyo contenido será obtenido mediante un cálculo.
EJEMPLO 3.1 [Link]
Puedes encontrar este proyecto completo en la carpeta
HerramientasEntorno. Para usarlo en tu equipo tendrás
que editar el archivo de definición de conexiones, ajustando la ruta a la
base de datos, y a continuación tendrás que copiar dicho archivo a la
carpeta que contiene el ejecutable.
Comenzamos iniciando un nuevo proyecto vacı́o de tipo MULTI-DEVICE
APPLICATION y, como hicimos en el capı́tulo previo, agregaremos un módulo de
datos al mismo. Mediante la opción F ILE —U SE U NIT vincularemos el for-
mulario con el módulo de datos, a fin de poder acceder desde el primero a los
componentes de datos del segundo.
3.7.1 Conexión y selección de datos
Usando el Explorador de datos localizamos en el nodo M ICROSOFT ACCESS
DATABASE la base de datos de ejemplo DBDEMOS. Esta contiene una tabla lla-
mada customer. Hacemos clic sobre ella y la arrastramos hasta soltarla so-
bre el módulo de datos. Esta acción agregará al módulo de datos dos compo-
nentes: un TFDConnection y un TFDQuery. El primero tendrá en su pro-
piedad ConnectionDefName el valor DBDEMOS, apuntando a la definición
de conexión almacenada en el archivo de configuración global de FireDAC. El
segundo contendrá una consulta de selección para obtener todas las columnas y
filas de la tabla customer.
El único componente FireDAC adicional que necesita la aplicación serı́a un
TFDGUIxWaitCursor. Lo localizamos, en la Paleta de componentes o usando
el recuadro de búsqueda de IDE I NSIGHT, y lo insertamos también en el módulo
de datos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EN LA PRÁCTICA 113
NOTA
Al agregar los componentes con arrastrar y soltar desde el Explo-
rador de datos, en lugar de insertarlos y configurarlos manualmente como
hicimos en el capı́tulo previo, no es necesario añadir el componente
TFDPhysMSAccessDriverLink ya que se agregan las referencias a
los módulos necesarios automáticamente.
3.7.2 Configuración para la inspección de
actividad
Queremos examinar la actividad de la aplicación mientras operamos con ella, por
lo que vamos a añadir al módulo de datos un componente TFDMoniRemote-
ClientLink. Mediante sus propiedades Host y Port podemos configurar
la dirección del equipo y el puerto TCP/IP en que está a la escucha la utili-
dad FireDAC Monitor4 . Nos aseguramos de dar el valor True a su propiedad
Tracing.
A continuación seleccionamos el componente DbdemosConnection agre-
gado antes, vamos al Inspector de objetos, desplegamos la propiedad Params,
abrimos la lista asociada a la subpropiedad MonitorBy y elegimos la opción
mbRemote. Esto es todo lo que necesitamos hacer para poder inspeccionar la
actividad de la aplicación.
3.7.3 Edición de la consulta de selección de
datos
Abrimos el menú contextual asociado al componente CustomerTable, cuyo
tipo es TFDQuery, y seleccionamos la opción Q UERY E DITOR. Usamos el
Editor de consultas para modificar la consulta de selección, introduciendo la que
4
Podemos configurar el puerto de escucha de este programa mediante el campo P ORT de
la lista de parámetros de configuración, a la que se accede con la opción T OOLS —T RACE
O PTIONS.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
114 HERRAMIENTAS BDD EN DELPHI
se mostró anteriormente en el Listado 3.2. Con ella seleccionamos solamente
cinco columnas de la tabla, filtramos las filas según un parámetro sustituible y
fijamos el orden de las filas.
A continuación, aún en el Editor de consultas, abrimos la página PARAMS y
configuramos el parámetro RefDate, estableciéndolo como parámetro de en-
trada, de tipo ftDate y con el valor inicial que deseemos. Ahora podemos
cerrar el Editor de consultas.
Con el objetivo de configurar los campos de forma estática, en la fase de
diseño, abrimos el Editor de campos del mismo componente TFDQuery y elegi-
mos la opción A DD ALL FIELDS. Comprobaremos que los únicos campos que
aparecen son los cinco referenciados en la cláusula SELECT de la consulta.
3.7.4 Adición de un campo calculado
Además de los datos que recuperamos de la tabla, seleccionados en la ante-
rior consulta, también queremos que el programa muestre un dato adicional: el
número de dı́as transcurridos desde la última factura de cada cliente. Para ello
agregaremos al TFDQuery un campo calculado. Los pasos a seguir para ello
son los indicados a continuación:
1. Abrimos el menú contextual del Editor de campos y elegimos la opción
N EW FIELD.
2. Se abre la ventana N EW F IELD, en la que comenzamos por introducir el
valor DaysSinceLastInvoice como nombre del campo.
3. Seleccionamos Integer como tipo del nuevo campo y marcamos la opción
C ALCULATED, tal y como se mostró en la Figura 3.12. Hacemos clic en
OK para cerrar el cuadro de diálogo.
4. Seleccionamos el TFDQuery y, usando la página E VENTS del Inspector de
objetos, localizamos el evento OnCalcFields, haciendo doble clic sobre
él.
5. Introducimos en el método asociado a dicho evento el código mostrado en
el Listado 3.3, con el cual se calcula el valor que habrı́a de tomar el nuevo
campo.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EN LA PRÁCTICA 115
1 procedure [Link](DataSet: ⤦
Ç TDataSet);
2 begin
3 [Link] :=
4 DaysBetween([Link], ⤦
Ç [Link]);
5 end;
Listado 3.3 Expresión para obtener el valor del campo calculado
CustomerTableDaysSinceLastInvoice es el nombre que se ha dado
a la variable que representa al campo calculado, a partir del nombre que nosotros
introdujimos antes y usando como prefijo el nombre del componente TFDQuery.
Mediante su propiedad Value le asignamos el valor que debe tomar, calculando
la diferencia en dı́as5 entre la fecha actual, obtenida con Date, y la fecha de la
última factura. Esta se almacena en un formato de fecha propia de la base de
datos, por lo que usamos la propiedad AsDateTime para convertirla.
3.7.5 Diseño de la interfaz de usuario
Ya tenemos en nuestro módulo de datos todo lo que necesitamos. Ahora llega el
momento de diseñar la interfaz de usuario de la aplicación. Volvemos al formu-
lario, que estaba vacı́o, e introducimos los siguientes elementos:
TPanel: Este componente nos servirá como contenedor para los dos con-
troles siguientes. Asignamos el valor Top a su propiedad Align para colo-
carlo en la parte superior del formulario y, si es necesario, ajustamos su
altura.
TCheckBox: Su finalidad será permitir activar y desactivar la conexión
entre la interfaz y el conjunto de datos que va a mostrarse. Modificaremos
su propiedad Text asignándole el valor ’Activar conexión’.
TDateEdit: Servirá para introducir una fecha que nos permitirá filtrar las
filas mostradas, obteniendo únicamente aquellas que cuentan con facturas
5
Para poder usar la función DaysBetween tendremos que agregar el módulo
DateUtils a la cláusula uses del módulo de datos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
116 HERRAMIENTAS BDD EN DELPHI
a partir de la fecha indicada. Opcionalmente podemos colocar un control
TLabel delante para especificar su finalidad.
TGrid: Este control será el que muestre la información procedente de la
base de datos. Modificaremos su propiedad Align asignándole el valor
Client, de forma que ocupe todo el espacio disponible salvo el usado por
el TPanel.
El aspecto del formulario, una vez insertados los componentes indicados, serı́a
similar al que se muestra en la Figura 3.16. El TGrid no muestra aún infor-
mación dado que no hemos establecido la conexión con los componentes de
datos.
Figura 3.16 FORMULARIO FINALIZADA LA INSERCI ÓN DE COMPONENTES
3.7.6 Conexi´
on entre interfaz y datos
El paso siguiente consiste en vincular la interfaz de usuario, en este caso el
componente TGrid, con el conjunto de datos en el que reside la información sobre
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EN LA PRÁCTICA 117
la que se trabajará. Para esta tarea recurriremos al asistente de Live Bindings
que se describió anteriormente. El procedimiento a completar es el descrito a
continuación:
1. Usamos la opción B IND V ISUALLY del TGrid para abrir el panel L IVE -
B INDINGS D ESIGNER y hacemos clic en el botón que pone en marcha el
asistente.
2. Seleccionamos la opción L INK A GRID WITH A DATA SOURCE en la
primera página y hacemos clic en el botón N EXT.
3. En el segundo paso tenemos dos opciones: seleccionar un componente
cuadrı́cula ya existente en la interfaz de usuario o bien crear una nueva
y agregarla al formulario. Usamos la primera, eligiendo el componente
TGrid que aparece como único elemento de la lista y de nuevo hacemos
clic en N EXT.
4. A continuación tenemos que seleccionar el conjunto de datos que quere-
mos enlazar con la cuadrı́cula anterior eligiendo, como en el caso previo,
entre uno existente o creándolo. Nosotros escogeremos el TFDQuery que
tenemos en el módulo de datos.
5. Finalmente podemos marcar una opción que añadirı́a a la interfaz un control
de navegación. Nos limitamos a hacer clic en el botón F INISH.
Al terminar, el asistente introducirá en el formulario dos componentes: un
TBindSourceDB, vinculado al TDBQuery, y un TBindingList para man-
tener la lista de vı́nculos.
NOTA
Si ahora damos el valor True a la propiedad Active del TDBQuery,
en el TGrid deberı́amos ver la información obtenida de la base de datos.
Dejaremos dicha propiedad con el valor False que tiene por defecto.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
118 HERRAMIENTAS BDD EN DELPHI
3.7.7 Código de activación y filtrado
Solo resta un pequeño detalle para finalizar el desarrollo de la aplicación: ges-
tionar el evento OnChange del control TCheckBox que determina si la conexión
estará activa o no. Será en ese mismo controlador de evento donde establez-
camos el filtro para las filas, asignando el valor introducido en el TDateEdit al
parámetro RefDate de la consulta. Hacemos doble clic sobre el TCheckBox
e introducimos el código siguiente:
1 procedure TMyForm.CheckBox1Change(Sender: TObject);
2 begin
3 with [Link] do
4 begin
5 ParamByName(’RefDate’).AsDate := [Link];
6 Active := [Link];
7 end;
8 end;
Listado 3.4 Código asociado al evento OnChange del TCheckBox
3.7.8 Probando la aplicación
Antes de lanzar la ejecución del proyecto, para lo cual basta con pulsar F9,
abriremos el FireDAC Monitor. Esto permitirá que nuestro programa pueda con-
tactar con dicha aplicación, a fin de examinar toda la actividad relativa al acceso
a la base de datos.
Al ejecutar el programa el formulario aparecerá vacı́o. Incluso si activamos la
conexión es probable que continúe vacı́o, ya que la fecha de filtrado por defecto
será la actual. No tenemos más que desactivar la conexión, establecer una fecha
previa y volver a activarla. El resultado deberı́a ser similar al que se muestra en la
Figura 3.17, aunque lógicamente los datos dependerán de la fecha que hayamos
introducido.
Cada vez que activemos la conexión comprobaremos, mediante el FireDAC
Monitor, cómo se desencadena un buen número de eventos. Cada uno de ellos
contiene la información de las operaciones realizadas. Puedes realizar una prueba
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EN LA PRÁCTICA 119
Figura 3.17 EL PROGRAMA EN FUNCIONAMIENTO
muy sencilla: haz clic en la ciudad de una de las filas de datos y modifı́cala, se-
leccionando después otra fila p ara t ransmitir l os c ambios. A c ontinuación, en
el FireDAC Monitor, localiza la lı́nea en la que se envı́a el comando UPDATE
CUSTOMER, como se ha hecho en la Figura 3.18, y haz clic sobre ella para ver
los detalles. En el panel inferior podrás ver la sentencia SQL utilizada para efec-
tuar la actualización. En ella se modifica el valor de la columna CITY y se toma
como referencia (en la cláusula WHERE) el número de cliente. De forma similar
podrı́amos inspeccionar cualquier operación de manipulación y transferencia de
datos.
3.7.9 Preparar la aplicación para su des-
pliegue
Ejecutar la aplicación en el mismo equipo donde hemos llevado a cabo el desa-
rrollo no implica ningún problema, ya que los parámetros de la conexión están
accesibles en el archivo global de configuración de FireDAC y la base de datos
se encuentra donde se copió originalmente al instalar Delphi. Si llevásemos el
programa a otro ordenador, en el que no estuviese instalado Delphi, al intentar
ejecutarlo obtendrı́amos un mensaje de error.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
120 HERRAMIENTAS BDD EN DELPHI
Figura 3.18 INSPECCIONAMOS LA OPERACI ÓN DE ACTUALIZACI ÓN
Los pasos para preparar nuestro proyecto para su despliegue son muy sencillos
en este caso, ya que estamos utilizando una base de datos local. Básicamente
tenemos que hacer dos cosas:
Copiar el archivo [Link], en el que está alojada la base de datos,
desde su carpeta de origen a la carpeta que contendrá nuestro ejecutable.
Usar el FireDAC Explorer para crear un nuevo archivo de conexiones con-
teniendo únicamente la entrada DBDEMOS. Esta apuntarı́a con una ruta re-
lativa al archivo anterior. El archivo [Link] también
acompañarı́a a nuestro ejecutable.
Teniendo esos elementos, podrı́amos copiar la carpeta con el ejecutable, la
base de datos y el archivo de definición de conexiones a cualquier otro equipo y
deberı́a funcionar.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
RESUMEN 121
3.8 Resumen
Al finalizar este capı́tulo ya conocemos la mayor parte de las herramientas de tra-
bajo con bases de datos integradas en Delphi, incluidas utilidades externas como
FireDAC Explorer y FireDAC Monitor que nos permitirán realizar la mayor parte
de las tareas sin tener que recurrir a herramientas de terceros, todo ello desde el
propio entorno de Delphi. En el ejercicio desarrollado en la parte final se ha
mostrado cómo usar en la práctica la mayor parte de esas herramientas, creando
una nueva aplicación en la que se ha usado una base de datos y una interfaz
distinta a la implementada en el capı́tulo previo.
Con la base adquirida en este y el capı́tulo anterior, en el próximo nos con-
centraremos en los detalles del desarrollo de aplicaciones FireMonkey y VCL
que usan FireDAC, poniendo especial énfasis en los aspectos relacionados con
la interfaz de usuario.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Capı́tulo 4
INTERFACES DE USUARIO
CON CONEXIÓN A DATOS
En el capı́tulo anterior el objetivo era conocer herramientas del entorno de Delphi
relacionadas con el trabajo con bases de datos mediante FireDAC pero de tipo
genérico, dejando intencionadamente de lado aquellas dirigidas al desarrollo de
la interfaz de usuario de la aplicación. La única excepción fue la introducción
del L IVE B INDINGS D ESIGNER, al tratarse de un elemento fundamental para el
seguimiento del ejercicio propuesto.
En contraposición, este capı́tulo está completamente centrado en el tema de
las interfaces de usuario con conexión a orı́genes de datos, ya estén basadas en
la biblioteca de componentes VCL o en la FMX. Comenzaremos por analizar las
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
124 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
diferencias entre dichas bibliotecas, a fin de que podamos decidir cuál nos con-
viene en cada caso. Posteriormente se describirán algunos aspectos especı́ficos
de los componentes VCL con conexión a datos y, finalmente, se profundizará en
el uso de los LiveBindings.
4.1 VCL versus FMX
Desde hace años Delphi incorpora dos bibliotecas de componentes con un mismo
fin: facilitar el diseño de interfaces de usuario siguiendo el enfoque RAD. La
VCL es una vieja conocida para todos aquellos que lleven un tiempo usando
Delphi, ya que es la biblioteca que acompaña a Delphi desde su primera versión,
habiendo sobrevivido a la multiplataforma CLX que se introdujo con Kylix. Se
trata, en consecuencia, de una opción madura y muy probada, en la que se ha
trabajado de manera ininterrumpida desde 1995.
La FMX, también conocida como FireMonkey, es una biblioteca de com-
ponentes de desarrollo mucho más reciente, pero la inversión hecha en ella y
el número de versiones que lleva integrada con Delphi, la hacen también una
opción segura para el futuro.
Los apartados de esta sección resumen los aspectos más destacables de estas
dos bibliotecas. Nuestro propósito es ayudarte a decidir cuál de las dos elegir en
cada caso, según el proyecto cuyo desarrollo vayas a afrontar.
4.1.1 Plataformas objetivo
Una de las diferencias fundamentales entre VCL y FMX, quizá la más impor-
tante a la hora de tomar una decisión en cuanto a cuál de las dos elegir, es el
conjunto de plataformas objetivo para las que puede compilarse un proyecto que
las utilice.
La VCL nació estrechamente ligada a la API de Windows, concretamente a
la plataforma que conocemos como Win321 . Con el tiempo, hace relativamente
1
En realidad la primera versión de la VCL, incluida en Delphi 1, era de 16 bits. Fue
a partir de Delphi 2, tras el lanzamiento de Windows 95, cuando se incluye Win32 como
plataforma objetivo.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
VCL VERSUS FMX 125
poco, se añadió también la posibilidad de compilar para Win64, aprovechando
ası́ la posibilidad de acceder a más memoria. Tras crear un nuevo proyecto
basado en la VCL comprobaremos que la única plataforma agregada es Win32.
Podemos utilizar la opción A DD P LATFORM del menú contextual para añadir
otras plataformas. Como se muestra en la Figura 4.1, la única opción adicional
disponible es Win64.
Figura 4.1 VCL SOLO EST Á DISPONIBLE PARA W IN 32 Y W IN 64.
FireMonkey fue adquirida a la empresa KSDev y forma parte de Delphi desde
la versión XE2, por lo que no ha sido diseñada para ser compatible con la VCL.
Se trata de una biblioteca de componentes multiplataforma, con la que es posi-
ble crear proyectos tanto para ordenadores de escritorio con Windows (Win32
y Win64) y Mac OS X como para dispositivos móviles con iOS y Android. De
hecho, a partir de Delphi XE7 al iniciar un proyecto de tipo M ULTI -D EVICE
ya encontramos todas las plataformas en el Gestor de proyectos (véase la Figura
4.2), sin necesidad de agregarlas manualmente.
En cuanto a selección de plataformas objetivo, por tanto, la FMX está clara-
mente por delante de la VCL, siendo de hecho la única opción en caso de que
necesitemos desarrollar para plataformas móviles.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
126 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
Figura 4.2 FMX TAMBI ÉN EST Á DISPONIBLE PARA OS X, IOS Y ANDROID
4.1.2 Hardware y software de base
VCL y FMX fueron desarrolladas en momentos muy diferentes, algo que es
apreciable en el aprovechamiento que ambas hacen de los recursos del sistema
y que influye a simismo e n e l h ardware y s oftware b ásico s obre e l q ue pueden
ejecutarse.
La FMX es una biblioteca pensada para explotar la potencia de las actuales
GPU (Graphics Processing Units), un elemento imprescindible en el ordenador
o dispositivo donde vayan a ejecutarse las aplicaciones. En el caso de Windows
además es preciso contar con una versión reciente de DirectX, la API gráfica
que permite a FMX comunicarse con la GPU en lugar de OpenGL que es la API
usada en el resto de plataformas.
Prácticamente todos los componentes FMX cuentan con propiedades con las
que es posible aplicar transformaciones (RotationAngle, RotationCenter
y Scale en la Figura 4.3) y animaciones visuales, facilitando la composición de
interfaces de usuario muy atractivas y dinámicas que, además, están preparadas
para su funcionamiento en dispositivos con pantallas táctiles. Asimismo es posi-
ble crear interfaces gráficas 3D.
En contraposición, la VCL se apoya para hacer su trabajo en la clásica API
gráfica de Windows (GDI), en lugar de DirectX u OpenGL. Esto hace que gráfica-
mente sea menos potente, pero a cambio es la única opción si queremos desarro-
llar aplicaciones para versiones de Windows relativamente antiguas pero todavı́a
muy extendidas, como es el caso de Windows XP.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
VCL VERSUS FMX 127
Figura 4.3 PROPIEDADES PARA APLICAR TRANSFORMACIONES EN FMX
NOTA
Los componentes tanto de la VCL como de la FMX, al igual que los de
FireDAC según se indicó anteriormente, pasan a formar parte del ejecutable
de los proyectos una vez que son compilados, por lo que en ningún caso es
necesario redistribuir junto a la aplicación módulos asociados estas biblio-
tecas.
En consecuencia en la elección de una biblioteca u otra también influirá el he-
cho de que el proyecto deba o no funcionar en equipos no tan potentes o con ver-
siones anteriores de Windows que, bien sabemos, continúa siendo la plataforma
mayoritaria de propósito general en el escritorio.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
128 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
4.1.3 Compatibilidad hacia atrás
Son muchas las aplicaciones desarrolladas con versiones previas de Delphi que
aún siguen en funcionamiento, proyectos que es necesario seguir manteniendo
de forma periódica. La mayor parte de ellas están basadas en la VCL, no exis-
tiendo una vı́a de conversión directa de VCL a FMX. Además hay dos razones
adicionales para seguir utilizando la VCL en estos casos:
Componentes de terceros: Son multitud los casos en que se utilizaron com-
ponentes de terceros, no propios de la VCL pero compatibles con esta, que
únicamente están disponibles para dicha biblioteca. Sin romper esa depen-
dencia no es posible convertir el proyecto para usar la FMX, a menos que el
desarrollador de esos componentes ofrezca en algún momento una versión
FMX de los mismos.
Servicios Win32 no en la FMX: La VCL es una biblioteca especı́fica para
Windows, de ahı́ que ofrezca componentes que aprovechan las caracterı́sticas
especı́ficas de este sistema, mediante APIs especı́ficas (encontramos mu-
chos de estos componentes, por ejemplo TTaskbar y TJumpList, en
las páginas W IN 32, S YSTEM y W IN 3.1 de la Paleta de componentes,
mostradas en la Figura 4.4). Si se necesitan esos servicios deberemos seguir
utilizando la VCL, al menos que en el futuro la FMX también cubra dichas
necesidades.
Figura 4.4 COMPONENTES ESPEC ÍFICOS PARA WINDOWS EN LA VCL
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
FIREDAC Y APLICACIONES VCL 129
En resumen, elegir entre la VCL y la FMX a la hora de iniciar el desarrollo de
un nuevo proyecto con Delphi puede no resultar sencillo, influyendo los aspectos
citados y posiblemente algunos más. No obstante, un aspecto que no nos forzará
a decantarnos por una u otra es la necesidad de utilizar FireDAC, ya que en
ambos casos dispondremos fundamentalmente de las mismas posibilidades.
NOTA
La RTL, biblioteca de servicios básicos de Delphi que opera debajo de
la VCL y FMX, es totalmente multiplataforma y compatible con ambas bi-
bliotecas de componentes.
4.2 FireDAC y aplicaciones VCL
Los componentes FireDAC, ası́ como las herramientas que se describieron en el
capı́tulo previo, están también disponibles cuando se trabaja con proyectos basa-
dos en la VCL. Vamos a comprobarlo en la práctica creando un simple programa
análogo al del ejercicio final del capı́tulo previo, pero basado en la VCL en lugar
de la FMX.
EJEMPLO 4.1 [Link] y [Link]
En las carpetas GUIconVCL y GUIconFMX encontrarás dos versiones
de un mismo proyecto, el primero utilizando componentes enlazados a
datos clásicos de la VCL y el segundo con idéntica funcionalidad pero
usando la FMX. En ambos casos existe un formulario principal con una
cuadrı́cula de datos y un formulario secundario en el que se usan otros
controles enlazados a datos.
Partimos creando un nuevo proyecto usando la plantilla VCL F ORMS A PPLI -
CATION , tal y como se muestra en la Figura 4.5. El proyecto contará inicial-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
130 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
mente con un formulario vacı́o, pero la información de diseño de este se almace-
nará en un módulo con extensión .dfm en lugar de .fmx.
Figura 4.5 CREAMOS UN NUEVO PROYECTO BASADO EN LA VCL
4.2.1 Módulo de datos y componentes FireDAC
Lo primero que haremos será agregar al proyecto un módulo de datos. Este tipo
de contenedor es idéntico al que se usa en proyectos FMX, por lo que puede alo-
jar exactamente los mismos tipos de componentes. Acto seguido reproduciremos
los pasos indicados a continuación:
1. Localizamos en el Explorador de datos la tabla customer de la conexión
DBDEMOS y la arrastramos hasta el módulo de datos. Esto insertará y con-
figurará los componentes TFDConnection y TFDQuery.
2. Añadimos el componente TFDGUIxWaitCursor y, si queremos, también
el TFDPhysMSAccessDriverLink, aunque este último no serı́a nece-
sario al haber creado la conexión desde el Explorador de datos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
FIREDAC Y APLICACIONES VCL 131
3. Finalmente agregamos al módulo de datos un componente TDataSource2 ,
al que llamaremos CustomerDataSource, usando su propiedad DataSet
para conectarlo con el TFDQuery, tal y como se aprecia en la Figura 4.6.
También daremos el valor True a su propiedad Enabled.
Figura 4.6 AGREGAMOS AL M ÓDULO DE DATOS LOS COMPONENTES FIREDAC
A fin de poder hacer referencia a los elementos del m ódulo de datos desde el
formulario, activamos este último en el diseñador y usamos la opción F ILE —U SE
U NIT para agregar una referencia al primero.
NOTA
Al igual que hicimos en el ejercicio del capı́tulo previo, podrı́amos usar
el Editor de consultas y el Editor de campos del componente TFDQuery
a fin de ajustar la consulta, seleccionar los campos que deseamos tener y
definir campos calculados. El procedimiento serı́a exactamente el mismo
descrito entonces.
2
La finalidad de este componente es actuar como intermediario entre los componentes
que representan conjuntos de datos, como TFDQuery y TFDTable, y los controles que
componen la interfaz de usuario.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
132 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
4.2.2 Interfaz de usuario
A continuación tendremos que diseñar la interfaz de usuario encargada de mostrar
los datos procedentes del TFDQuery. Lo hacemos dando los pasos siguientes:
1. Agregamos un control TPanel al formulario, dando el valor Top a su pro-
piedad Align. Eliminaremos el contenido de la propiedad Caption para
quitar el texto que aparece en el panel.
2. Insertamos dentro del TPanel un TCheckBox que nos servirá para activar
y desactivar la conexión. Usamos la propiedad Caption para establecer
su tı́tulo.
3. Por último introducimos en el formulario un TDBGrid, control análogo al
TGrid de la FMX: una cuadrı́cula que puede ser conectada a un origen de
datos. Usamos su propiedad DataSource para conectarlo al componente
TDataSource que tenemos en el módulo de datos (véase la Figura 4.7).
Figura 4.7 INTERFAZ DE USUARIO CON CUADR ÍCULA Y TCH E C KBO X
Solamente nos queda escribir el código que se encargará de habilitar o desha-
bilitar la conexión con la base de datos en respuesta al estado del TCheckBox.
Haremos doble clic sobre este, para abrir el gestor correspondiente al evento
OnClick, e introducimos el código mostrado a continuación:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
COMPONENTES VCL CON CONEXIÓN A DATOS 133
1 procedure TForm3.CheckBox1Click(Sender: TObject);
2 begin
3 [Link] := [Link];
4 end;
Listado 4.1 Código asociado al control TCheckBox
Ahora ya podemos ejecutar el proyecto y comprobar su funcionamiento que,
como cabrı́a esperar, es casi idéntico al de la aplicación FMX que creábamos
como ejercicio al final del capı́tulo previo (no hay posibilidad de filtrado por
fecha y las columnas mostradas son otras). Las diferencias han sido puntuales:
la inclusión de un TDataSource y el control que actúa como cuadrı́cula es un
TDBGrid en lugar de un TGrid.
Aunque la conexión entre el origen de datos y la cuadrı́cula la hemos estable-
cido manualmente, editando la propiedad DataSource del TDBGrid, también
podrı́amos haber usado el L IVE B INDINGS D ESIGNER para realizar dicha tarea
tal y como hicimos en el capı́tulo previo.
4.3 Componentes VCL con conexión
a datos
Al trabajar con la VCL y bases de datos, creando interfaces de usuario que fa-
cilitan la visualización y edición de información alojada en una base de datos,
tradicionalmente se ha recurrido al uso de controles especı́ficos con conexión a
datos (data-aware controls).
Estos controles usan el prefijo TDB en sus nombres, por ejemplo TDBEdit,
TDBMemo, TDBNavigator o TDBGrid. Todos ellos se alojan en una página
especı́fica de la Paleta de componentes: DATA C ONTROLS (véase la Figura 4.8).
Los componentes con conexión a datos eran imprescindibles en la VCL, ya
que los controles análogos sin el prefijo TDB no podı́an ser enlazados a un ori-
gen de datos por procedimientos RAD, debiendo recurrirse a escribir código de
sincronización en ambos sentidos: desde el origen de datos al control y vice-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
134 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
Figura 4.8 CONTROLES VCL CON CAPACIDAD PARA CONECTARSE A DATOS
versa. Esto, no obstante, ha cambiado completamente en las últimas versiones
de Delphi, gracias a la introducción de los LiveBindings3 .
Todos los componentes que usan el prefijo TDB cuentan con una propiedad
que no encontramos en el resto de controles: DataSource. La finalidad de esta
es enlazar el control con un componente TDataSource que, a su vez, estarı́a
vinculado al origen de datos, por ejemplo un TDBQuery. El TDataSource es
un intermediario genérico, de forma que el origen de datos podrı́a ser cualquier
otro derivado de TDataSet. Dependiendo del tipo de control utilizado, además
de la anterior también es usual encontrar la propiedad DataField. Su finalidad
es enlazar el control con un campo concreto del origen de datos.
3
Las primeras implementaciones de LiveBindings para la VCL, allá por la versión XE2,
no siempre ofrecı́an la vı́a sencilla y rápida disponible para la FMX, pero esto es algo que se
ha corregido en las versiones actuales
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LIVEBINDINGS 135
En principio, por tanto, y salvo que dependamos de controles vinculados a
datos muy específicos, no hay muchas razones objetivas para decantarse por el
uso de los controles tipo TDB, enlazados a un TDataSource, en lugar de usar
los mismos controles que utilizaríamos en cualquier interfaz de usuario y recurrir
al mecanismo de LiveBindings. De esta forma podemos seguir básicamente los
mismos procedimientos de diseño para las interfaces de usuario, indistintamente
de que la biblioteca de base sea VCL o FMX.
4.4 LiveBindings
Mostrar en una interfaz de usuario información procedente de un RDBMS o
algún otro origen de datos, permitiendo también su edición, implica contar con
algún tipo de conexión entre los controles de interfaz y los componentes de
acceso a los datos. Los primeros estarı́an alojados en un formulario, mientras
que los segundos normalmente residirán en un módulo de datos. Dicha conexión
ha ser bidireccional, de forma que las acciones del usuario sobre los datos mos-
trados en la interfaz se transfieran adecuadamente al origen que los almacena.
El modelo descrito en la sección previa, disponible únicamente para
componentes VCL, implica la duplicación de muchos de los controles con el
simple objeto de agregar un vı́nculo a un TDataSource. Ası́ tenemos el
control TDBEdit que es funcionalmente equivalente al TEdit, pero dispone de
las propiedades DataSource y DataField. Lo mismo se aplica a controles
como TDBMemo, TDBImage o TDBCheckBox, equivalentes a TMemo,
TImage y TCheckBox, respectivamente. De esta forma se limitan los
elementos que es posible incluir en una interfaz de usuario con conexión a datos,
únicamente pueden usarse de forma directa los controles de la página DATA
CONTROLS, y por otra también se restringen las propiedades de esos controles
que se vincularán a los datos.
Mediante LiveBindings, que es un motor de evaluación de expresiones en
las que los operandos participantes son propiedades de objetos, el anterior es-
quema se expande a fin de permitir el uso de cualquier control y la conexión de
cualquiera de sus propiedades a campos del origen de datos. Los objetos actúan
como origen o bien como objetos controlados, pudiendo invertir dicho papel en
caso necesario. Incluso se contempla la posibilidad de conexión entre propieda-
des de un mismo componente.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
136 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
La principal ventaja de LiveBindings, ya apuntada antes, es que está disponible
tanto en la VCL como en la FMX, por lo que es una opción de desarrollo ho-
mogénea con independencia de la biblioteca de componentes de interfaz que se
elija.
4.4.1 Componentes LiveBindings esenciales
Desde la versión XE2 de Delphi, en la que se introdujo esta técnica para FMX y
VCL, hasta hoy se han producido algunos cambios en los componentes asociados
a LiveBindings. Los componentes TBindScope y TBindScopeDB, por
ejemplo, fueron sustituidos por una jerarquı́a más flexible de componentes
derivados de TBaseLinkingBindSource, como TBindSourceDB. Otros
sin embargo se han mantenido, como es el caso de los componentes
TBindingsList y TBindNavigator. La mayorı́a de ellos los encontramos
en las páginas LIVEBINDINGS y LIVEBINDINGS MISC de la Paleta de componentes
(véase la Figura 4.9.)
Figura 4.9 COMPONENTES FUNDAMENTALES DE LIVEBINDINGS
Por regla general no tendremos que agregar ni configurar manualmente estos
componentes, dado que el L IVE B INDINGS D ESIGNER nos permite establecer
todas las conexiones con operaciones de arrastrar y soltar o bien mediante el
asistente que conocimos en el capı́tulo previo. No obstante, analicemos qué hace
el diseñador cuando establecemos un vı́nculo entre un origen de datos y controles
de interfaz desde el citado diseñador.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LIVEBINDINGS 137
Contexto del origen de datos
Para conectar un origen de datos, por ejemplo la información de un TFDQuery,
con uno o más controles de interfaz lo primero que se precisa es un compo-
nente que facilite el contexto del origen de datos. Este lo aportará un compo-
nente derivado de la clase TCustomBindSourceDB. En la Paleta de compo-
nentes encontramos dos descendientes de dicha clase: TBindDataSourceDB
y TBindDataSourceDBX. Usarı́amos el primero para conectar con orı́genes
de datos FireDAC y el segundo si estuviésemos utilizando dbExpress. Nos cen-
traremos en el primero ya que vamos a usar FireDAC.
El componente TBindDataSourceDB cuenta con una propiedad DataSet
que le permite conectarse al TFDQuery antes citado o, alternativamente, a un
TFDTable o algún otro derivado de TFDDataSet. A su vez, el componente
TBindDataSourceDB se conectará a los controles de interfaz mediante la
propiedad DataSource del enlace de LiveBindings apropiado.
En el L IVE B INDINGS D ESIGNER un TBindDataSourceDB muestra, en
su parte superior, el nombre del conjunto de datos a que está conectado, enu-
merando a continuación las columnas que obtiene del mismo (véase la Figura
4.10). Mediante arrastrar y soltar es posible conectar todo el conjunto de datos,
con controles como TGrid, o bien columnas individuales, con controles como
TEdit, TCheckBox, TMemo, etc.
Enlaces de LiveBindings
Los vínculos entre el componente TBindSourceDB y los controles que
forman la interfaz se establecen mediante componentes de enlace
LiveBindings, tales como TLinkControlToField,
TLinkListControlToField o TLinkGridToDataSource. No
encontraremos estos elementos en la Paleta de componentes. La herramienta
encargada de gestionarlos es el diseñador asociado al componente
TBindingsList.
NOTA
Los componentes de la familia TLinkXXXToYYY actúan como interme-
diarios entre el TBindSourceDB y los controles de interfaz de usuario.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
138 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
Figura 4.10 CONFIGURACI ÓN DE UN TBI N DDA T ASO U R C EDB
Aunque podemos agregar al formulario un TBindingsList tomándolo de
la Paleta de componentes, lo habitual es que se añada automáticamente en cuanto
establezcamos un enlace visualmente, desde el L IVE B INDINGS D ESIGNER. Al
hacer doble clic sobre ese componente se abrirá la ventana mostrada en la Figura
4.11. El panel de la izquierda permite agrupar los enlaces por categorı́as, mien-
tras que el de la derecha muestra el nombre y descripción de cada uno de los
enlaces existentes en la categorı́a elegida.
En lugar de crear el enlace entre el TBindSourceDB y los controles de in-
terfaz mediante operaciones de arrastrar y soltar, que generalmente es lo más
cómodo, podemos usar el primer botón de la barra de herramientas de esta ven-
tana para crearlos manualmente. El primer paso serı́a seleccionar el tipo de en-
lace que necesitamos, eligiéndolo de la lista a la que da paso el citado botón
(véase la Figura 4.12). El segundo la configuración del enlace usando el Inspec-
tor de objetos.
Las propiedades que generalmente nos interesará configurar de un enlace son
las indicadas a continuación:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
LIVEBINDINGS 139
Figura 4.11 DISE ÑADOR ASOCIADO AL COMPONENTE TBI N D I N G SLI S T
Figura 4.12 LISTA DE CLASES DE ENLACES LiveBindings
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
140 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
DataSource: Apuntará al TBindSourceDB que establece el contexto
del origen de datos que se quiere utilizar.
Control: Establecerá el control que se enlazará al contexto de origen
de datos indicado por la propiedad anterior. Puede ser cualquiera de los
controles existentes en el formulario.
FieldName: En caso de que el control no sea de tipo cuadrı́cula, sino que
se vincula a una sola columna del origen de datos, esta propiedad permite
elegir dicha columna.
Direction: Mediante esta propiedad se determina cuál será el sentido en
el que fluirán los datos a través del enlace. Las posibles configuraciones son
tres: del origen de datos hacia el control (linkDataToControl), del
control hacia el origen de datos (linkControlToData) o bidireccional
(linkBidirectional). Esta última configuración es la más habitual y
por ello es la que se utiliza por defecto.
4.4.2 Adición y enlace de controles
Ya conocemos tres métodos distintos para agregar controles a un formulario y
enlazarlos con un origen de datos:
Usando el asistente del panel L IVE B INDINGS D ESIGNER, concretamente
las opciones L INK A CONTROL WITH A FIELD y L INK A GRID WITH A
DATA SOURCE . Estas añaden automáticamente el control al formulario si
es preciso, insertando también el TBindingsList si no existiese ya. A
continuación se agrega el componente de enlace adecuado y se configura.
Agregando manualmente el control a la interfaz de usuario y a continuación,
también usando el L IVE B INDINGS D ESIGNER, establecer el vı́nculo con
operaciones de arrastrar y soltar. Estas añaden al TBindingsList el
componente TLinkXXXToYYY apropiado y lo configuran, estableciendo
el vı́nculo entre el origen de datos y el control.
Usando el diseñador asociado al TBindingsList para crear manual-
mente el componente de enlace y configurarlo mediante el Inspector de
objetos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
DISEÑO DE UNA INTERFAZ CON CONTROLES SIMPLES Y NAVEGACIÓN 141
Figura 4.13 INSERTAR Y ENLAZAR UN NUEVO CONTROL A UN CAMPO DE DATOS
Existe al menos una vı́a adicional para realizar esta misma tarea. Una vez que
disponemos del TBindSourceDB en el L IVE B INDINGS D ESIGNER, pode-
mos usar el menú contextual de cualquier columna para ejecutar la opción L INK
TO NEW CONTROL. Esta abrirá una lista de controles disponibles para el tipo de
campo elegido (véase la Figura 4.13). No tenemos más que elegir el que nos in-
terese para agregarlo automáticamente la formulario y enlazarlo con la columna
elegida.
4.5 Diseño de una interfaz con con-
troles simples y navegación
En los ejercicios propuestos hasta ahora hemos recurrido a la visualización de
datos en una cuadrı́cula, representada por el control TGrid o TDBGrid según
los casos. Las cuadrı́culas permiten mostrar en una estructura tabular un conjunto
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
142 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
de filas y columnas, facilitando asimismo las operaciones de edición de datos. No
obstante, no siempre es la opción más apropiada para el diseño de una interfaz
de usuario conectada a datos.
Si la información a mostrar no se ajusta a una estructura tabular, por ejemplo
al existir campos de texto extensos o imágenes, la mejor alternativa suele ser el
diseño de un formulario con controles simples4 , que permiten operar sobre una
única fila de datos, incluyendo los controles de navegación apropiados. Veamos
cómo hacerlo a través de un nuevo ejercicio.
EJEMPLO 4.2 [Link]
Puedes encontrar este proyecto completo en la carpeta
VCLLiveBindings. Puedes abrirlo y ejecutarlo directamente
ya que no existe conexión con origen de datos externo alguno.
4.5.1 Origen de los datos
A fin de concentrarnos en el diseño de la interfaz y la conexión de los controles a
los datos, que es lo que nos interesa en este caso, vamos a prescindir del módulo
de datos y de los componentes FireDAC para acceso a una base de datos con-
creta. En su lugar usaremos el componente TPrototypeBindSource, cuya
finalidad es generar datos de prueba para escenarios como el actual.
Tras agregar ese componente al formulario abriremos el Editor de campos,
con la opción F IELDS E DITOR de su menú contextual, y a continuación hare-
mos clic en el primer botón del editor vacı́o, haciendo ası́ aparecer la lista de
columnas disponibles. Como se aprecia en la Figura 4.14, tenemos columnas
de cualquier tipo: cadenas de caracteres, números enteros y en punto flotante,
fechas, booleanos, mapas de bits, etc.
Seleccionaremos las columnas siguientes para añadirlas al Editor de campos:
ContactBitmaps, ContactNames, ContactTitles, Currency
4
Entendiendo en este contexto que un control simple es aquél que se vincula a una sola
columna del origen de datos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
DISEÑO DE UNA INTERFAZ CON CONTROLES SIMPLES Y NAVEGACIÓN 143
Figura 4.14 PODEMOS SELECCIONAR LAS COLUMNAS A INCLUIR
y LoremIpsum (tipo ftTstrings). Con esto tenemos a nuestra disposición
un grupo de campos con distintos tipos: textos, números, imágenes y conjunto
de lı́neas de texto. Si abrimos el L IVE B INDINGS D ESIGNER los encontraremos
como columnas en el componente TPrototypeBindSource.
4.5.2 Diseño de la interfaz de usuario
Mediante el menú contextual asociado a cada columna usaremos la opción L INK
TO NEW CONTROL para agregar los controles al formulario y, al mismo tiempo,
configurar el enlace con el origen de datos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
144 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
Figura 4.15 DISPOSICI ÓN DE LOS CONTROLES Y ENLACES AL ORIGEN DE DATOS
Elegiremos un TImage, dos TLabeledEdit, un TMaskEdit y un TMemo,
respectivamente al orden en que añadimos las columnas. La disposición de los
controles podrı́a ser la que se muestra en la Figura 4.15.
A continuación podrı́amos abrir el editor del componente TBindingsList
y examinar los objetos que se han añadido para establecer los enlaces. Todos
ellos serán de tipo TLinkControlToField. Lo que cambiará de uno a otro
será los valores asignados a las propiedades Control y FieldName.
4.5.3 Controles de navegación
Los controles que hemos introducido en el formulario servirán para mostrar las
columnas de una fila de datos, por lo que será preciso a ñadir algún control que
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
OTRAS CONFIGURACIONES DE DATOS 145
facilite la navegación por las filas que contuviese el conjunto de datos. Para ello
recurriremos al menú contextual del componente TPrototypeBindSource
y elegiremos la opción A DD N AVIGATOR. Esta insertará en el formulario un
control TBindNavigator ya vinculado al origen de datos. La única propie-
dad que cambiaremos de dicho control será Align, a la que daremos el valor
alBottom para colocarlo en la parte inferior del formulario.
Con esto ya hemos terminado el desarrollo de este ejercicio. Podemos ejecutar
el proyecto y el resultado deberı́a ser parecido al que se muestra en la Figura 4.16.
Usando los controles de navegación podemos movernos por las filas del conjunto
de datos, ası́ como eliminar, agregar y modificar filas.
Figura 4.16 LA APLICACI ÓN VCL EN FUNCIONAMIENTO
Aunque en este caso hemos utilizado un origen de datos artificial, represen-
tado por el componente TPrototypeBindSource, el procedimiento habrı́a
sido idéntico si hubiésemos partido de un proyecto con un módulo de datos y
componentes FireDAC conectados a una base de datos real, como hicimos en
ejercicios previos.
4.6 Otras configuraciones de datos
Hasta ahora hemos aprendido a construir, tanto con la VCL como la FMX, for-
mularios basados en cuadrı́culas y también en controles simples, en el caso de
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
146 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
la VCL recurriendo a los antiguos TDBxxx y también, en el apartado previo,
usando LiveBindings. Básicamente estas son todas las combinaciones posibles
que podemos encontrar. A partir de ellas, no obstante, se construyen configu-
raciones más especı́ficas. Estas son el objeto de la última sección del presente
capı́tulo.
NOTA
A partir de este punto, tanto en el capı́tulo actual como en los posterio-
res, siempre basaremos los ejercicios en proyectos de tipo M ULTI -D EVICE
A PPLICATION con FMX y usando LiveBindings. Los procedimientos para
trabajar con la VCL, en cuanto a la conexión a datos y composición de la
interfaz, serı́an equivalentes según se ha descrito en las secciones previas.
La naturaleza del modelo de datos relacional, con sus reglas de normalización,
contribuye a que en las bases de datos existan referencias entre las tablas. Dichas
relaciones pueden ser de tipo uno a uno, de forma que a una fila de una tabla le
corresponde solo una fila de otra, o bien uno a muchos, en cuyo caso tenemos una
relación de tipo maestro/detalle. Veamos cómo gestionar este tipo de relaciones
al diseñar una interfaz de usuario con acceso a datos en Delphi.
4.6.1 Relaciones maestro/detalle
En este tipo de relación a una fila de una tabla le corresponden una o más filas de
otra. La primera tabla es la maestra y la segunda es la tabla de detalle. Los casos
más tı́picos son los de las tablas de facturas y lı́neas de factura o de pedidos y
lı́neas de pedido. La tabla de facturas almacena toda la información de cabecera
de una factura: nombre, dirección e identificación del cliente, fecha en que se
emite, importe total antes y después de impuestos, etc. Todos esos datos no hay
que repetirlos para cada lı́nea de detalle de la factura, en la que se especifica el
artı́culo o servicio que está facturándose, el precio unitario, la cantidad, etc. La
separación en dos tablas de una entidad fı́sica única, como es la factura, per-
mite reducir la información redundante. Lógicamente, ha de existir una columna
común que relacione a ambas tablas, permitiendo localizar todas las lı́neas de
una factura.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
OTRAS CONFIGURACIONES DE DATOS 147
Al trabajar con FireDAC este tipo de relaciones se definen atendiendo a los
siguientes pasos:
Cada tabla, la maestra y la de detalle, estarı́a representada por su propio
componente TFDQuery, conectados ambos al mismo TFDConnection.
El TFDQuery asociado a la tabla de detalle incluirá en la consulta un pa-
rámetro de filtrado de las filas, de forma que solo se obtengan aquellas que
correspondan a la fila actualmente activa en la tabla maestra.
El TFDQuery de la tabla de detalle se vinculará con la tabla maestra me-
diante la propiedad MasterSource. Para ello se utilizará un componente
TDataSource como intermediario entre ambas tablas.
En caso necesario se usarán las propiedades MasterFields y
DetailFields del TFDQuery de detalle para establecer el campo
común que vincula a ambas tablas, indicando los campos de la tabla maestra
y de detalle que lo forman. En la mayorı́a de los casos esto no es preciso ya
que dicho campo tendrá el mismo nombre que el parámetro usado en la
consulta del incluida en el TFDQuery.
Una vez que se ha establecido la relación apropiada entre los componentes de
datos, el diseño de la interfaz se llevará a cabo según los procedimientos que ya
conocemos. Lo habitual es que la información común, la de la tabla maestra, se
disponga en un formulario usando controles individuales, mientras que los datos
de detalle se recogen en algún tipo de cuadrı́cula.
4.6.2 Campos de búsqueda
Cuando la relación entre dos tablas es de uno a uno, no de uno a muchos, lo que
suele necesitarse es que un campo de una tabla sirva para buscar un dato en la
otra. Es una técnica común conocida como lookup field y FireDAC nos ofrece
las opciones necesarias para definirlos.
En la sección 3.7.4, durante el desarrollo de un ejercicio, se describió cómo
definir un campo calculado. Entre las opciones disponibles en la ventana usada
para ello encontraremos la que permite crear campos de búsqueda.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
148 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
4.6.3 En la práctica
Veamos cómo componer una interfaz de usuario en la que exista tanto una relación
maestro/detalle como un campo de búsqueda. Volveremos a apoyarnos en la base
de datos DBDEMOS, ya que es una base de datos Access local que no precisa de
mayor configuración ni infraestructura para su uso.
EJEMPLO 4.3 [Link]
Puedes encontrar este proyecto completo en la carpeta
MaestroDetalle. Su funcionamiento depende de la base de
datos Access DBDEMOS, por lo que necesitarás realizar los ajustes
necesarios en el archivo de definiciones de FireDAC.
Una vez iniciado el nuevo proyecto, de tipo M ULTI -D EVICE A PPLICATION,
los pasos que debemos seguir son los descritos a continuación, en los apartados
siguientes.
Preparación del módulo de datos
Agregaremos el proyecto un nuevo módulo de datos y, sirviéndonos del Explo-
rador de datos, arrastraremos hasta él las tablas Orders, Items y Customer
de la base de datos DBDEMOS. Esto agregará un TFDConnection, con los
parámetros de conexión a la base de datos, y tres TFDQuery representando a
las tres tablas.
Tenemos que añadir un componente TDataSource, ası́ como el habitual
TFDGUIxWaitCursor. Usaremos la propiedad DataSet del primero para
enlazarlo con la tabla Orders. Esto nos permitirá definir la relación maestro/de-
talle entre los componentes OrdersTable e ItemsTable. Para ello haremos
lo siguiente:
1. Abrimos el menú contextual del TFDQuery asociado a la tabla Items y
elegimos la opción Q UERY E DITOR para abrir el editor de consultas.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
OTRAS CONFIGURACIONES DE DATOS 149
2. Agregamos a la consulta ya existente en el editor un filtro de búsqueda, me-
diante la cláusula WHERE OrderNo = :OrderNo, tal y como se aprecia
en la parte derecha de la Figura 4.17.
Figura 4.17 ESTABLECEMOS EL V ÍNCULO ENTRE TABLA MAESTRA Y DE DETALLE
3. Cerramos el Editor de consultas y recurrimos al Inspector de objetos para
establecer la propiedad MasterSource del mismo componente, seleccio-
nando el TDataSource que anteriormente habı́amos vinculado a la tabla
de pedidos.
4. Opcionalmente podemos fijar el valor de las propiedades MasterFields
y DetailFields. Estas propiedades tienen asociado un editor como el
de la Figura 4.18, en el que podemos seleccionar columnas de las lista de
la izquierda y agregarlas a la de la derecha. En este caso solamente se
precisarı́a la columna OrderNo que es el dato común entre la tabla maestra
y la de detalle: el número de pedido.
A continuación tenemos que definir el campo de búsqueda que nos permitirá
obtener, a partir del código de cliente que se almacena en la tabla Orders, el
nombre de la empresa cliente alojada en la tabla Customer. En este caso el
procedimiento se compone de los siguientes pasos:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
150 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
Figura 4.18 SELECCI ÓN DE LOS CAMPOS PARA EL V ÍNCULO MAESTRO/DETALLE
1. Abrimos el menú contextual del componente OrdersTable y selecciona-
mos la opción F IELDS E DITOR a fin de abrir el Editor de campos. Este
estará inicialmente vacı́o.
2. Mediante la opción A DD F IELD del menú contextual del Editor de campos
agregamos los campos que vamos a necesitar: OrderNo, SaleDate y
CustNo. Estos contienen el código de pedido, fecha de la venta y código
del cliente, respectivamente.
3. Usando la opción N EW F IELD del Editor de campos accedemos al cuadro
de diálogo del mismo nombre, en el que procederemos a configurar el campo
de búsqueda.
4. Introducimos CustomerName como nombre del campo y seleccionamos
de la lista desplegable T YPE el tipo String.
5. En el apartado F IELD T YPE, que contiene las opciones de tipo de campo,
seleccionaremos el tipo L OOKUP. Esto activará los controles del apartado
L OOKUP D EFINITION, situado en la parte inferior de la ventana.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
OTRAS CONFIGURACIONES DE DATOS 151
6. La configuración del campo de búsqueda será la mostrada en la Figura 4.19.
Con ella establecemos que usando el campo CustNo de la tabla actual
(OrdersTable) se buscará coincidencia con el campo CustNo en el
componente CustomerTable, recuperándose el contenido de su columna
Company.
Figura 4.19 CONFIGURACI ÓN DEL CAMPO DE B ÚSQUEDA
Lo que obtendríamos en el campo CustomerName, por tanto, sería el nombre
de la empresa a la que corresponde el pedido. Con esto tenemos todo lo
necesario en cuanto a configuración de acceso a datos. Solamente quedarı́a dar
el valor True a la propiedad Active de los TFDQuery, a fin de que podamos
ver durante el diseño la información sobre la que estamos trabajando.
Diseño de la interfaz de usuario
En el proyecto tenemos un formulario vacı́o, al que vamos a añadir los controles
necesarios para recorrer los pedidos y las lı́neas que le correspondan. Lo primero
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
152 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
que debemos hacer es usar la opción F ILE —U SE U NIT para agregar una refe-
rencia al módulo de datos, de forma que podamos acceder a los componentes
alojados en él.
Utilizando el L IVE B INDINGS D ESIGNER enlazamos las columnas de la tabla
de pedidos con dos controles TEdit y un TCalendarEdit. También agre-
garemos un TBindNavigator asociado a esa misma tabla. Recuerda que no
tienes más que abrir el menú contextual del TBindSource y elegir la opción
A DD N AVIGATOR. También introduciremos un control TGrid, vinculándola
con la tabla de lı́neas de pedido (ItemsTable). El enlace entre columnas de
datos y los controles introducidos en la interfaz de usuario son los mostrados en
la Figura 4.20.
Figura 4.20 ENLACES ENTRE COLUMNAS DE DATOS Y CONTROLES DE INTERFAZ
Puesto que toda la lógica que relaciona unas tablas con otras ya ha sido es-
tablecida en el módulo de datos, en el formulario no es preciso hacer nada más,
una vez agregados los controles, para poder navegar por los pedidos y ver por
cada uno de ellos la fecha, cliente a que corresponde y los productos incluidos
en el mismo. En la Figura 4.21 se muestra la aplicación en ejecución.
NOTA
Dado que no hemos agregado código alguno al proyecto, el formulario
solamente mostrará los datos si hemos dado el valor True a la propiedad
Active de los TFDQuery durante la fase de diseño.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
RESUMEN 153
Figura 4.21 EL PROGRAMA CON LA INTERFAZ MAESTRO / DETALLE EN
FUNCIONAMIENTO
4.7 Resumen
En este capı́tulo hemos conocido las diferencias fundamentales entre la VCL y la
FMX a la hora de desarrollar un proyecto Delphi con conexión a bases de datos,
ası́ como los procedimientos a seguir en cada uno de los casos. La conclusión
final serı́a que el uso de LiveBindings, con independencia de la biblioteca de
componentes elegida, nos ofrece la vı́a más flexible para establecer los enlaces
entre los datos y la interfaz, siendo además una vı́a común a VCL y FMX, por lo
que serı́a más sencillo cambiar de una a otra.
NOTA
Es posible utilizar LiveBindings para crear otros tipos de enlaces en-
tre propiedades de componentes, sin que estén implicadas bases de datos,
usando también expresiones a medida. Puedes encontrar más información
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
154 INTERFACES DE USUARIO CON CONEXIÓN A DATOS
sobre el uso en estos contextos en el libro La guı́a de Delphi, del mismo
autor y editorial.
Además hemos aprendido a diseñar varios de los tipos de interfaces con cone-
xión a datos más habituales: usando cuadrı́culas de datos, empleando controles
simples y combinando ambos enfoques para representar relaciones maestro/de-
talle e incluir campos de búsqueda.
Con esta base, en los capı́tulos siguientes abordaremos casos más especı́ficos
de aplicaciones Delphi con acceso a bases de datos locales, incluyendo el uso de
InterBase embebido, bases de datos de escritorio y bases de datos en memoria,
entre otros.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Capı́tulo 5
APLICACIONES CON
INTERBASE EMBEBIDO
A diferencia de SQLite o Microsoft Access, que son los tipos de bases de datos
que hemos utilizado en los ejercicios de capı́tulos previos, InterBase es un ver-
dadero RDBMS. Esto implica que la base de datos puede contener objetos adi-
cionales, como las vistas, las funciones, los procedimientos almacenados y los
disparadores, que no son habituales en bases de datos de escritorio.
InterBase puede ser instalado en un servidor y actuar como cualquier otro
RDBMS, como puede ser SQL Server u Oracle, pero también puede utilizarse en
otras configuraciones menos habituales para un servidor de datos. Una de ellas
es el uso embebido en las aplicaciones, de forma que el propio motor que ges-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
156 INTERBASE EMBEBIDO
tiona los datos es distribuido con el programa, no siendo precisas instalaciones
adicionales ni acceso remoto a los datos (como es habitual en un servidor).
En este capı́tulo vamos a conocer el procedimiento que seguirı́amos para uti-
lizar InterBase embebido en un proyecto desarrollado con Delphi, poniéndolo en
práctica en un ejercicio cuyo resultado podremos ejecutar tanto en un ordenador
de escritorio como en dispositivos móviles.
5.1 InterBase ToGo
InterBase, como servidor de datos, puede ser instalado en Windows, GNU/Linux
y OS X, estando disponible tanto en versiones de 32 como de 64 bits. Como
ocurre al trabajar con cualquier otro RDBMS alojado en un servidor, un equipo
distinto del que ejecuta la aplicación, nuestro programa utilizarı́a un controlador
FireDAC para comunicarse con el software cliente del RDBMS que, a su vez,
se comunicarı́a a través de red con el servidor para ejecutar las tareas encomen-
dadas.
También podemos utilizar InterBase como servidor datos local, configuración
en la que el software cliente y el servidor residen en el mismo equipo. La co-
municación entre ambos componentes, por tanto, puede ser directa en lugar de
a través de TCP/IP. Este modo de trabajo local, para el cual precisarı́amos la li-
cencia Developer del producto, nos permitirá crear nuevas bases de datos, definir
las estructuras de tablas, vistas, etc., e introducir la información que se precise.
Todas estas son tareas que, por regla general, efectuaremos en un ordenador de
escritorio con un servidor local de InterBase.
Finalmente tenemos InterBase ToGo que, en esencia, es el núcleo del motor
que gestiona las bases de datos InterBase, un módulo redistribuible que hace
posible que las aplicaciones desarrolladas con Delphi accedan a bases de datos
InterBase directamente, sin software de comunicaciones cliente ni un servidor
de datos. InterBase ToGo está disponible para múltiples sistemas operativos,
incluyendo los OS móviles iOS y Android, lo que le convierten en la edición
más multiplataforma de InterBase.
InterBase ToGo, por tanto, es ideal para el uso embebido (o empotrado) en
aplicaciones móviles, aportando muchos de los beneficios de trabajar con un
verdadero RDBMS pero sin los costes y complejidades de su instalación y ad-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HERRAMIENTAS INTERBASE PARA DESARROLLO 157
ministración. Únicamente hay que incluir, al desplegar la aplicación, el motor
de InterBase ToGo, el archivo que contiene la base de datos y el archivo de
licencia correspondiente.
5.1.1 Licencias ToGo e IBLite
InterBase ToGo es, como componente software, un producto único. No obs-
tante puede ser utilizado bajo dos tipos diferentes de licenciamiento, a los que se
denomina comercialmente ToGo e IBLite. La primera tiene un cierto coste
económico, mientras que la segunda es gratuita. Las diferencias fundamentales
entre ambas ediciones se indicaron en la sección 2.2.1 (capítulo 2).
Delphi incluye una versión de desarrollo de InterBase ToGo que nos permite
utilizar este producto durante un tiempo limitado, con el objetivo de facilitar
la realización de pruebas. Para distribuir aplicaciones con este RDBMS
tendríamos que adquirir la licencia correspondiente o, en su defecto, optar
por IBLite siempre que nuestro proyecto pueda adecuar su
funcionamiento a las limitaciones de esta versión gratuita.
NOTA
En [Link]
en/IBLite_and_IBToGo_Licensing_in_RAD_Studio se de-
talla el proceso de registro a seguir para obtener una licencia gratuita de
IBLite, ası́ como para utilizar la licencia de desarrollo de la edición ToGo.
5.2 Herramientas InterBase para de-
sarrollo
Crear un proyecto en el que van a utilizarse bases de datos InterBase requerirá
que durante la fase de desarrollo, en el equipo donde estemos trabajando, po-
damos operar sobre dichas bases de datos. Para ello lo habitual es que utilice-
mos el Local InterBase Server que se incluye con Delphi. Este es un servidor
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
158 INTERBASE EMBEBIDO
local mediante el que podemos conectar con cualquier base de datos InterBase y
trabajar con ella mediante las herramientas para desarrollo.
5.2.1 InterBase Manager
La primera herramienta con la que tendremos que familiarizarnos será el Inter-
Base Manager, una utilidad mediante la que se controla el estado del servidor
local de InterBase y se configuran sus propiedades. La interfaz de esta consola
de administración es la mostrada en la Figura 5.1.
Figura 5.1 INTERFAZ DEL INTERBASE MANAGER
Lo habitual es que InterBase se inicie automáticamente cada vez que se ponga
en marcha el sistema, pero mediante la opción M ANUAL del apartado S TARTUP
M ODE podemos optar por un inicio manual1 . En este caso utilizarı́amos el botón
1
Para poder cambiar el modo de inicio es necesario que el servidor esté parado, por lo que
primero harı́amos clic en el botón S TOP y después modificarı́amos la opción de inicio.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
HERRAMIENTAS INTERBASE PARA DESARROLLO 159
adjunto al apartado S TATUS para iniciar o detener el servidor local de datos, a
demanda.
El botón S ERVER P ROPERTIES simplemente abre un panel en la parte in-
ferior de la ventana, indicando el número de bases de datos y conexiones acti-
vas. Mediante el botón G UARDIAN P ROPERTIES podremos saber el número
de reinicios que ha sufrido el servidor de datos. Este botón será inaccesible en
caso de que el servidor local de InterBase esté ejecutándose como un servicio.
El guardián es un proceso que vigila constantemente el estado del servidor y, en
caso de que haya problemas, procede a reiniciarlo.
Fundamentalmente usaremos esta herramienta para asegurarnos de que el
servidor está en funcionamiento y, en caso necesario, proceder a iniciarlo. De
esta forma podremos acceder a él desde el entorno de Delphi, nuestras aplica-
ciones o la consola de InterBase.
5.2.2 La consola de InterBase
Una vez que el servidor local de InterBase está en funcionamiento, la herramienta
a la que recurriremos habitualmente es la consola de InterBase. La encontrarás
buscando ibconsole en el menú/pantalla I NICIO de Windows. Desde esta
utilidad podremos comunicarnos tanto con el servidor local como con cualquier
servidor InterBase remoto. No tenemos más que registrar el servidor con el que
deseemos trabajar, usando para ello las opciones del menú contextual asociado
al nodo I NTER BASE S ERVER (raı́z del panel izquierdo).
Tras conectar con una base de datos, por ejemplo la clásica Employee2 que
se incluye como ejemplo con InterBase, podremos examinar todos los obje-
tos que contiene, acceder a sus propiedades y, si fuese preciso, modificarlos.
También encontraremos en el menú contextual asociado a cada tipo de objeto las
opciones necesarias (véase la Figura 5.2) para crearlos, por ejemplo definiendo
nuevas tablas, vistas, procedimientos almacenados, etc.
Asimismo desde la consola también es posible efectuar tareas de manteni-
miento sobre las bases de datos, efectuando copias de seguridad, gestionando
los privilegios de los usuarios o analizando los datos de rendimiento asociados
2
Las credenciales por defecto para acceder a esta base de datos son SYSDBA y
MASTERKEY.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
160 INTERBASE EMBEBIDO
Figura 5.2 CONSOLA DE INTERBASE
a la misma. Todas estas opciones nos permitirán preparar la base de datos que
vayamos a utilizar desde nuestra aplicación, comenzando por la creación de la
propia base de datos, la definición de las tablas y demás objetos, creación de
usuarios y, finalmente, obtención del archivo que contiene toda la información.
Este será un archivo con extensión .gdb, totalmente compatible con InterBase
ToGo e IBLite.
NOTA
La información relativa a las opciones ofrecidas por la consola de
InterBase puedes encontrarla en [Link]
products/interbase/IBXE3Update3/ToGoQuickStart/
[Link]
En las secciones posteriores de este capı́tulo, en las que aprenderemos a
acceder a bases de datos InterBase con FireDAC, utilizaremos la citada base de
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
INTERBASE Y FIREDAC 161
datos de ejemplo Employee. No obstante, los procedimientos a seguir serı́an
idénticos con cualquier base de datos que hubiésemos creado a medida para nues-
tro proyecto.
5.3 InterBase y FireDAC
FireDAC incluye los controladores necesarios para comunicarse con InterBase,
indistintamente de cuál sea su versión: ToGo, IBLite, servidor local o remoto.
No tenemos más que agregar el componente TFDPhysIBDriverLink a nues-
tro proyecto y establecer los parámetros adecuados para que el componente
TFDConnection use dicho controlador. También podemos arrastrar y soltar
desde el Explorador de datos, como hemos hecho en capı́tulos previos, dejando
que el diseñador incluya todos los elementos necesarios.
Además de los componentes de uso común que ya conocemos, como el citado
TFDConnection o el componente TFDQuery, en la página FIREDAC
SERVICES de la Paleta de componentes encontraremos también varios
especıficos para trabajar con InterBase. La finalidad de estos, brevemente, es la
indicada a continuación:
TFDIBConfig: Permite poner una base de datos offline, para efectuar ta-
reas de mantenimiento, y online, lista para trabajar de nuevo, ası́ como mo-
dificar algunos parámetros de configuración como el tamaño de la caché, el
dialecto de SQL, etc.
TFDIBValidate: Facilita el acceso a las operaciones de validación y
reparación de bases de datos.
TFDIBBackup y TFDIBRestore: Mediante estos dos componentes es
posible realizar una copia de seguridad de una base de datos y recuperarla
si fuese necesario.
TFDIBSecurity: Los métodos de este componente hacen posible agre-
gar, modificar y eliminar cuentas de usuario de la base de datos, entre otras
operaciones relacionadas con la seguridad.
Todas estas operaciones pueden ser completadas desde la consola de Inter-
Base, pero una vez desplegada la información es habitual que dicha herramienta
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
162 INTERBASE EMBEBIDO
no esté disponible. Con los componentes anteriores es posible integrar la misma
funcionalidad en una aplicación. En la mayorı́a de los casos no hay más que fa-
cilitar los parámetros de acceso a la base de datos e invocar al método adecuado.
NOTA
Los componentes TFDIBxxx permiten operar tanto sobre bases de datos
InterBase como Firebird.
5.4 Caso práctico
Veamos a través del desarrollo de un ejercicio práctico cómo utilizar InterBase
embebido en una aplicación. Concretamente utilizaremos IBLite para facili-
tar la visualización de información almacenada en la base de datos de ejemplo
Employee.
Dado que el objetivo es comprobar cómo podemos incluir IBLite en el des-
pliegue del proyecto a distintos dispositivos, incluyendo móviles, iniciaremos
un nuevo proyecto de tipo M ULTI -D EVICE A PPLICATION, usando la plantilla
que genera un proyecto con un formulario vacı́o. Desde este punto de partida
seguiremos los procedimientos descritos en los siguientes apartados para cons-
truir la aplicación.
EJEMPLO 5.1 [Link]
Puedes encontrar este proyecto completo en la carpeta IBEmbebido.
Es posible que tengas que realizar ajustes en la configuración de des-
pliegue de la aplicación, según el sistema en que quieras ejecutarlo y su
configuración.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CASO PRÁCTICO 163
5.4.1 Configuración de la conexión
Añadiremos el proyecto un módulo de datos, a fin de separar los componentes
FireDAC de la interfaz de usuario. El primer componente que insertaremos en
el módulo de datos será un TFDConnection, haciendo doble clic sobre él
para abrir la ventana de configuración (véase la Figura 5.3). Ajustaremos los
parámetros siguientes:
Figura 5.3 CONFIGURACI ÓN DE CONEXI ÓN A LA BASE DE DATOS
Controlador: Desplegamos la lista D RIVER ID y seleccionamos el ele-
mento IBL ITE, estableciendo ası́ el controlador adecuado para trabajar con
esta base de datos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
164 INTERBASE EMBEBIDO
Base de datos: En el campo DATABASE introducimos la ruta3 y nombre de
la base de datos [Link]. Podemos copiar dicha base de datos a
la carpeta de nuestro proyecto, a fin de simplificar el posterior despliegue a
otros dispositivos. Esta ruta nos permitirá trabajar durante la fase de diseño,
pero será necesario adecuarla posteriormente.
Credenciales: Introducimos el valor sysdba en el apartado U SER N AME
y el valor masterkey en el campo PASSWORD. Estas son las credenciales
por defecto de InterBase. También daremos el valor False a la propiedad
LoginPrompt del TFDQuery para que no se soliciten las credenciales al
intentar conectar.
Finalizada la configuración, podemos usar el botón T EST de la ventana an-
terior o bien dar el valor True a la propiedad Connected del TFDQuery,
comprobando ası́ que la conexión es posible.
NOTA
En este proyecto no vamos a utilizar un archivo de definición de co-
nexiones, sino que almacenaremos todos los parámetros en el propio
TFDConnection con el objetivo de poder ajustarlos en ejecución, tal y
como se explicará más adelante.
5.4.2 Selección de datos
El objeto de la aplicación será facilitar la consulta de departamentos de una
empresa, obteniendo la lista de empleados de cada departamento y, por cada
empleado, su historial de cambios de salario. Por tanto tendremos que
introducir en el módulo de datos tres componentes TFDQuery. Estos se
vincularán automáticamente el anterior TFDConnection. A continuación
usaremos el editor de consultas para configurar los datos a obtener por cada
uno:
3
Es importante preceder la ruta con localhost: a fin de que la conexión mediante
IBLite funcione desde el IDE de Delphi.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CASO PRÁCTICO 165
1 SELECT * FROM DEPARTMENT
Listado 5.1 Consulta para el componente DepartmentTable
1 SELECT * FROM EMPLOYEE
2 WHERE DEPT_NO = :DEPT_NO
Listado 5.2 Consulta para el componente EmployeeTable
1 SELECT * FROM SALARY_HISTORY
2 WHERE EMP_NO = :EMP_NO
Listado 5.3 Consulta para el componente SalaryHistoryTable
Como puede apreciarse, EMPLOYEE es la tabla de detalle respecto a los
datos de DEPARTMENT, mientras que SALARY HISTORY es la tabla de de-
talle respecto a la primera. Tenemos, por tanto, dos relaciones maestro/detalle
en cascada. Para terminar de configurarlas deberemos añadir dos componentes
TDataSource al módulo de datos, enlazando cada uno con una tabla maes-
tra. A continuación usaremos la propiedad MasterSource de las dos tablas
de detalle fijando el vı́nculo.
Para terminar con la configuración de datos, introduciremos en el modulo un
TFDGUIxWaitCursor y un TDFPhysIBDriverLink. El módulo quedará
finalmente como se muestra en la Figura 5.4. Podemos dar el valor True a la
propiedad Active de los tres TFDQuery a fin de ver los datos en el formulario
mientras lo diseñamos.
5.4.3 Diseño de la interfaz
Volvamos al formulario vacı́o con que contaba el proyecto inicialmente. Lo
primero que haremos será agregar una referencia al módulo de datos. Como
ya sabemos podemos hacerlo mediante la opción F ILE —U SE U NIT.
Dado que pretendemos que la aplicación se utilice en cualquier tipo de dispo-
sitivo, incluidos los que no contemplan el uso de múltiples ventanas, basaremos
la interfaz de usuario un único formulario estructurado en tres secciones distin-
tas, usando para ello un control TTabControl. Tras agregar este elemento al
formulario reproduciremos los pasos indicados a continuación:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
166 INTERBASE EMBEBIDO
Figura 5.4 COMPONENTES FIREDAC AGREGADOS AL M ÓDULO DE DATOS
1. Damos el valor Client a la propiedad Align del TabControl para
que ocupe todo el espacio disponible. Elegimos la opción None para la
propiedad TabPosition a fin de ocultar las pestañas de las páginas.
2. Abrimos el menú contextual del TTabControl y elegimos la opción A DD
TTAB I TEM para agregar una nueva página. Esta ocupará el mismo espacio
asignado al TTabControl.
3. Introducimos en el TTabItem un TToolBar. El valor de la propiedad
Align tomará automáticamente el valor Top. Insertamos en ese compo-
nente un TLabel y asignamos el valor Departamentos a su propiedad
Text.
4. Añadimos un TListView al mismo TTabItem, dándole el valor Client
a su propiedad Align. Daremos a este componente el nombre (propiedad
Name) ListViewDEPARTMENT.
5. Repetimos los pasos 2 a 4 agregando dos TTabItem adicionales con la
misma estructura: un TToolBar, que además del TLabel también con-
tendrán un TButton, y un TListView.
6. Configuraremos los TButton, que quedarán situados en el extremo iz-
quierdo de sus respectivos contenedores TToolBar, asignando el valor
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CASO PRÁCTICO 167
backtoolbutton a sus propiedades StyleLookup4 y asignando el
texto Volver a sus propiedades Text, respectivamente.
La estructura general de la interfaz de usuario, y las relaciones entre contene-
dores y controles contenidos, será la mostrada en la Figura 5.5. En ella pueden
verse también los nombres asignados a los distintos TListView.
Figura 5.5 ESTRUCTURA DE LA INTERFAZ DE USUARIO
5.4.4 Enlace con los datos
El siguiente paso será vincular cada uno de los TListView con su origen de
datos. También los TLabel incluidos en la parte superior del segundo y tercer
TTabItem estarán vinculados a un campo de datos.
Para empezar tendremos que agregar al formulario tres TBindSourceDB,
usando su propiedad DataSet para vincularlos a los componentes TFDQuery
4
Esta propiedad tiene asociada una lista desplegable de la que podemos elegir el estilo
que se le quiera dar al botón.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
168 INTERBASE EMBEBIDO
que tenemos en el módulo de datos. De esta forma ya podremos acceder a sus
datos desde el L IVE B INDINGS D ESIGNER, panel que abriremos con la opción
B IND V ISUALLY de cualquiera de los TListView.
Encontrándonos en el diseñador visual de LiveBindings, mediante operaciones
de arrastras y soltar estableceremos las conexiones mostradas en la Figura 5.6.
La propiedad [Link] de los TListView corresponde al texto que se
mostrarı́a en cada elemento de la lista. Con la propiedad [Link]
se introduce una cabecera de separación entre elementos, cuyo tı́tulo serı́a el
contenido de la columna enlazada.
Figura 5.6 CONFIGURACI ÓN DE ENLACE A DATOS DEL FORMULARIO
Con esta configuración c onseguimos q ue e l p rimer T
ListView m uestre el
nombre de cada departamento, el segundo el nombre de los empleados que co-
rresponden al mismo y el tercero el historial de cambios de salario de un
empleado. La relación maestro/detalle entre estas tablas se estableció
explıcitamente
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CASO PRÁCTICO 169
en el módulo de datos, mediante el uso de parámetros en las consultas y la con-
figuración de la propiedad MasterDataSource, por lo que en la interfaz no
es necesario especificar nada adicional.
5.4.5 Gestión de los eventos
La página inicialmente activa del TTabControl será la primera, con la lista
de departamentos, siendo necesario un mecanismo que permita abrir la lista de
empleados del departamento elegido y, una vez en ella, dar paso al historial
de cambios de salario del empleado que se seleccione. Además tendremos que
facilitar la vuelta atrás de cada paso.
Tendremos que controlar, por tanto, la pulsación sobre un elemento de los
dos primeros TListView y la pulsación sobre los botones de vuelta atrás.
Podrı́amos gestionar estas tareas definiendo acciones, con un TActionList,
que pudiesen reutilizarse a través de otros mecanismos, por ejemplo atajos de
teclado, pero por simplicidad nos limitaremos a asociar el código de cada tarea
directamente al gestor de eventos apropiado.
Los eventos a controlar son OnItemClick en los TListView y OnClick
en los TButton. En ambos casos el cambio de una página a otra se efectúa con
una simple asignación a la propiedad ActiveTab del TTabControl, como
se muestra en el siguiente listado:
1 procedure [Link](const Sender:⤦
Ç TObject;
2 const AItem: TListViewItem);
3 begin
4 [Link] := TabItem2;
5 end;
6
7 procedure TfrmMain.Button1Click(Sender: TObject);
8 begin
9 [Link] := TabItem1;
10 end;
11
12 procedure [Link](const Sender: ⤦
Ç TObject;
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
170 INTERBASE EMBEBIDO
13 const AItem: TListViewItem);
14 begin
15 [Link] := TabItem3;
16 end;
17
18 procedure TfrmMain.Button2Click(Sender: TObject);
19 begin
20 [Link] := TabItem2;
21 end;
Listado 5.4 Eventos de navegación por la interfaz
5.4.6 Comprobación de la aplicación
En este momento el proyecto está preparado para que comprobemos su fun-
cionalidad, en el mismo equipo en que ha sido desarrollado y habiendo activado
el acceso a datos durante la fase de diseño, estableciendo la propiedad Active
de los TFDQuery. No tenemos más que pulsar F9 y verificar que se muestra la
lista de departamentos obtenida de la base de datos InterBase, que al seleccionar
uno de ellos aparece la lista de empleados y que es posible acceder al historial
de cambios de salario de estos, tal y como se muestra en la Figura 5.7.
Si estas pruebas son correctas podemos pasar a la siguiente fase, preparando el
proyecto para su despliegue en otras plataformas. En caso contrario tendrı́amos
que revisar5 toda la configuración de componentes y código para detectar el pro-
blema que pudiese existir.
5.5 Configuración de despliegue
La configuración actual de nuestro proyecto le permite funcionar en el mismo
equipo en que se ha desarrollado, pero no se comportarı́a correctamente si
simplemente llevásemos el ejecutable a otro dispositivo, especialmente en el caso
5
Recuerda que tienes el proyecto completo a tu disposición en el repositorio de código
asociado al libro.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONFIGURACIÓN DE DESPLIEGUE 171
Figura 5.7 EL PROGRAMA EN FUNCIONAMIENTO EN WINDOWS
de iOS y Android. Es preciso introducir algunos cambios en el programa, por
una parte, y ajustar la configuración de despliegue para cada sistema, por otra.
Ese es el objetivo de esta última sección del capı́tulo.
5.5.1 Ruta de la base de datos
El primer cambio que hemos de introducir afecta a la configuración del compo-
nente TFDConnection, concretamente a la ruta en la que supuestamente ha
de encontrarse el archivo [Link] conteniendo la base de datos. Dicha
ruta existe en nuestro ordenador, pero no estará disponible en un dispositivo iOS
o Android ya que en estos está restringido el acceso de las aplicaciones a las
ubicaciones de almacenamiento. Además el controlador que estamos utilizando
para acceder a la base de datos también ha de ser distribuido con la aplicación,
ası́ como la correspondiente licencia.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
172 INTERBASE EMBEBIDO
Ocupémonos por ahora de la ubicación en que se encontrará la base de datos,
ajustando la configuración del TFDConnection adecuadamente. La base de
datos se copiará a la carpeta de documentos asociada a la aplicación, una ubi-
cación que podemos obtener mediante el método GetDocumentsPath de la
clase TPath. A dicha ruta agregaremos el nombre de la base de datos, usando
el separador que corresponda al sistema en que se ejecute la aplicación. Con este
fin usarı́amos el método Combine de la misma clase.
Nos interesa establecer la ruta correcta de la base de datos justo antes de
que el TFDConnection abra la conexión, algo que ocurrirá en cuanto se eje-
cute la aplicación ya que dimos el valor True a la propiedad Active de los
tres TFDQuery. Por ello localizaremos el evento OnBeforeConnect del
TFDConnection, introduciendo el código mostrado a continuación:
1 procedure [Link](Sender⤦
Ç : TObject);
2 begin
3 {$IF DEFINED(iOS) or DEFINED(ANDROID)}
4 [Link][’Database’] :=
5 [Link]([Link], ’[Link]’);
6 {$ENDIF}
7 end;
Listado 5.5 Establecemos la ubicación de la base de datos antes de conectar
Mediante la propiedad Params del componente TFDConnection
accedemos a los parámetros de configuración, modificando el parámetro
Database. Hemos usado directivas de compilación condicional a fin de que
este código únicamente se ejecute para sistemas Android e iOS. Para los demás
podríamos seguir utilizando un archivo de configuración con la cadena de
conexión, como hacíamos en capítulos previos, o bien incluir la base de datos6
en la misma carpeta de la aplicación y dejar la ruta simplemente como el
nombre de la base de datos.
6
Algunos sistemas operativos utilizan sistemas de archivos en los que se diferencia en-
tre mayúsculas y minúsculas, por lo que es importante que el valor asignado a Database
coincida exactamente con el nombre del archivo, incluyendo mayúsculas y minúsculas.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONFIGURACIÓN DE DESPLIEGUE 173
5.5.2 Redistribución de IBLite y su licencia
A continuación tendremos que incluir en el despliegue del proyecto tanto los
archivos redistribuibles de IBLite como la licencia que permitirá que este fun-
cione. Para ello usaremos la opción P ROJECT —D EPLOYMENT, abriendo el
panel de opciones de despliegue. Este cuenta en su parte superior con una barra
de herramientas entre las que encontraremos el botón A DD F EATURED F ILES,
encargado de abrir la ventana mostrada en la Figura 5.8. En ella marcaremos la
opción I NTER BASE T O G O para todas las plataformas o bien para aquellas en
las que vayamos a distribuir la aplicación. En este caso concreto, dado que hemos
utilizado IBLite en el proyecto, es importante que desmarquemos la distribución
del archivo reg [Link] y marquemos en su lugar reg [Link].
Estos archivos contienen la licencia de uso de InterBase ToGo e IBLite, respec-
tivamente.
Figura 5.8 COMPONENTES REDISTRIBUIBLES A AGREGAR AL PROYECTO
Al hacer clic en el botón OK comprobaremos cómo los archivos de IBLite
se agregan a cada una de las configuraciones. E n la l ista que hay en l a parte
superior derecha del panel seleccionaremos una plataforma y, si lo
deseamos, una configuración concreta, verificando los elementos a desplegar
junto con la aplicación.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
174 INTERBASE EMBEBIDO
5.5.3 Distribución de la base de datos
Además del controlador IBLite y su licencia, al desplegar la aplicación también
tendremos que copiar la propia base de datos [Link] en la ubicación
adecuada. La configuración para ello se establece desde el mismo panel en que
estamos trabajando. Con el segundo de los botones agregaremos el archivo a la
lista. A continuación lo seleccionaremos y usaremos el botón mostrado en la
Figura 5.9 para establecer la ruta en la que se copiarı́a en el destino. Esta última
acción hemos de efectuarla una vez por cada plataforma de despliegue, ya que
las ubicaciones varı́an según el sistema operativo de destino.
Figura 5.9 I NCLUIMOS LA PROPIA BASE DE DATOS ENTRE LOS ARCHIVOS A
DISTRIBUIR
En sistemas iOS la ubicación de destino ha de ser StartUp/Documents,
mientras que en Android dicha ruta serı́a assets/internal. Si fuésemos a
desplegar la aplicación en OS X o Win32/Win64 escogerı́amos la ubicación para
la que hubiésemos configurado la aplicación.
5.5.4 Configuración de permisos
En sistemas Android una aplicación que va a utilizar IBLite o InterBase ToGo
precisa solicitar al usuario, en el momento de la instalación, permisos para leer
y escribir en almacenamiento externo donde está alojada la base de datos, los
permisos se denominan R EAD EXTERNAL STORAGE y W RITE EXTERNAL
STORAGE , ası́ como para comunicarse con el gestor de datos (permiso I NTER -
Francisco Charte Danysoft
CONFIGURACIÓN DE DESPLIEGUE 175
NET ). Para activar esos permisos abriremos la ventana de opciones del proyecto,
iremos a la página U SES P ERMISSIONS y marcaremos los citados permisos,
como puede verse en la Figura 5.10.
Figura 5.10 CONFIGURACI ÓN DE PERMISOS DE LA APLICACI ÓN
NOTA
Para ampliar información sobre configuraciones de permisos, opciones
de despliegue, el uso del Asistente para despliegue o PAServer y muchos
otros detalles relacionados con el desarrollo para dispositivos móviles con
Delphi recomendamos el texto Desarrollo de aplicaciones iOS/Android con
Delphi, de la misma editorial y autor.
5.5.5 Comprobación de la aplicación
Habiendo finalizado la configuración de despliegue, estamos en disposición de
probar la aplicación en cualquier otro sistema. Para ello seleccionaremos la
plataforma objetivo en el Gestor de proyectos (véase la Figura 5.11). La rama
A NDROID nos permite probar tanto en el emulador de Android incluido con Del-
phi como en dispositivos reales, siempre que estos estén conectados por USB
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
176 INTERBASE EMBEBIDO
al equipo de desarrollo y apropiadamente configurados. Para desplegar en las
demás plataformas deberemos instalar el software PAServer correspondiente. En
el caso de iOS es posible usar un dispositivo fı́sico, conectado a un Mac, o bien
un emulador de iOS, para lo cual será preciso instalar el SDK de iOS para OS X
y XCode.
Figura 5.11 ELEGIMOS LA PLATAFORMA EN QUE SE DESPLEGAR Á EL PROYECTO
Asumiendo que quisiésemos probar en el emulador de iOS, iniciarı́amos el
PAS ERVER M ANAGER en OS X y a continuación, usando su menú desplegable
(véase la Figura 5.12) pondrı́amos en marcha un servidor. Este quedarı́a a la
escucha, esperando la comunicación desde el entorno de Delphi.
Figura 5.12 PASERVER MANAGER
Seleccionamos como plataforma de destino el emulador de iOS y
ejecutamos el proyecto. Si es la primera vez que desplegamos sobre iOS,
aparecerá un asistente que nos permitirá establecer la configuración de
comunicación: dirección
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONFIGURACIÓN DE DESPLIEGUE 177
IP o nombre del equipo con OS X y puerto en que está a la escucha PAServer.
Con estos datos se procederá a transferir todos los archivos necesarios al Mac,
encargándose PAServer de iniciar el emulador de iOS y lanzar la ejecución del
proyecto.
El programa, como puede apreciarse en la Figura 5.13, ofrece exactamente la
misma funcionalidad que ya habı́amos verificado en el equipo de desarrollo, si
bien su apariencia se ajusta al estilo de iOS.
Figura 5.13 LA APLICACI ÓN FUNCIONANDO EN EL EMULADOR DE IOS
En caso de que la aplicación no llegarse a mostrar la interfaz de
usuario, cerrándose automáticamente al intentar ejecutarla, lo más probable es
que exista un problema con la conexión a los datos. Lo más recomendable es
efectuar la conexión, dando el valor True a la propiedad Activede los
TFDQuery, en el evento OnCreate del formulario, protegiendo esas
sentencias para capturar cualquier excepción que se produzca y mostrarla en
pantalla.
Si, por ejemplo, no hubiésemos copiado el archivo de licencia de IBLite
al dispositivo, o estuviese en la localización incorrecta, al ejecutar la
aplicación
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
178 INTERBASE EMBEBIDO
aparecerı́a un error como el de la Figura 5.14. En estos casos podemos examinar
el directorio scratchdir que utiliza PAServer (véase la Figura 5.15) para
copiar los archivos que después se despliegan al emulador, verificando que están
todos los que deberı́an y en las ubicaciones correctas.
Figura 5.14 ERROR AL INTENTAR CONECTAR
Figura 5.15 COMPROBAMOS LOS ARCHIVOS EN LA CARPETA DE DESPLIEGUE
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
RESUMEN 179
5.6 Resumen
En este capı́tulo hemos comprobado cómo podemos utilizar exactamente los mis-
mos componentes FireDAC que utilizábamos para SQLite o Access para operar
sobre bases de datos InterBase, concretamente la edición embebida IBLite que
puede desplegarse en dispositivos móviles junto con nuestra aplicación. De esta
forma seguimos contando con un RDBMS completo incluso cuando nuestros
programas se ejecutan en iOS o Android. También hemos aprendido a configu-
rar el proyecto para distribuir los componentes de IBLite y su licencia de uso,
todo ello a través del desarrollo completo de un ejercicio.
Aunque IBLite e InterBase ToGo también pueden utilizarse en equipos de es-
critorio, en esta configuración posiblemente nos interese más recurrir al servidor
local de InterBase. También es posible que nos interese usar otros tipos de bases
de datos que son usuales cuando se almacena la información directamente en or-
denadores personales, en lugar de en servidores de datos o dispositivos móviles.
Este será el tema que se aborde en el siguiente capı́tulo.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Capı́tulo 6
DELPHI Y BASES DE DATOS
DE ESCRITORIO
Al desarrollar aplicaciones que van a utilizarse en ordenadores personales, ya
sean de escritorio o portátiles, es muy probable que surja la necesidad de operar
con orı́genes de datos exclusivos de estas plataformas. Los usuarios de orde-
nadores personales tienden a almacenar su información en el propio ordenador,
no en servidores de datos remotos, usando para ello formatos que, en general,
son especı́ficos de cada sistema operativo.
En Windows, por ejemplo, es habitual que se utilicen bases de datos Microsoft
Access y hojas de cálculo Microsoft Excel para guardar la información. En
muchos casos Excel se emplea como una base de datos simple, permitiendo que
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
182 BASES DE DATOS DE ESCRITORIO
personas que no tienen experiencia con bases de datos puedan estructurar su
información de manera más sencilla. También es habitual que los datos se alojen
directamente en archivos de texto, sencillamente usando comas u otro sı́mbolo
como separadores de campos y disponiendo cada entrada en una nueva fila.
El objetivo de este capı́tulo es que aprendamos a utilizar algunos de estos
orı́genes de datos, usados fundamentalmente en el escritorio. Ya sabemos cómo
conectar con bases de datos Access, lo hicimos en uno de los ejercicios de
capı́tulos previos, por lo que en las siguientes secciones nos ocuparemos de las
hojas de cálculo Access y los archivos de texto.
6.1 Acceso a datos en archivos de
Microsoft Excel
Microsoft Excel es una herramienta muy popular en distintos sistemas opera-
tivos, siendo muchos los profesionales que lo utilizan no solamente para efectuar
cálculos o elaborar gráficas, sino también como almacenes de d atos. La estruc-
tura de un archivo Excel se presta a este uso, ya que cada hoja puede ser tratada
como una tabla de una base de datos, estructurada en filas y columnas alojando
un dato en cada cruce.
No obstante Excel no es un gestor de datos, por lo que las operaciones que es
posible realizar sobre el contenido de las hojas no son las habituales del lenguaje
SQL. Se trata de una aplicación orientada al uso de fórmulas en las que existen
relaciones arbitrarias entre las celdillas, no aplicándose las restricciones a las que
estamos habituados en una base de datos.
6.1.1 FireDAC y Excel
A la hora de trabajar con información alojada en archivos Excel tenemos fun-
damentalmente dos alternativas: usar COM (Component Object Model) para
acceder al modelo de objetos Excel y controlarlo desde nuestra aplicación, lo
cual implica que Excel ha de estar instalado en el ordenador donde vaya a
utilizarse nuestra aplicación, o bien acceder al archivo en sı́ como si de una base
de datos se tratase.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ACCESO A DATOS EN ARCHIVOS DE MICROSOFT EXCEL 183
Entre los controladores de FireDAC no encontraremos uno especı́fico que nos
permita abrir un archivo Excel y acceder a su contenido. Por esta razón es nece-
sario recurrir a un acceso indirecto, utilizando para ello el controlador ODBC
para Excel ofrecido por Microsoft. Podemos usar dicho controlador sin necesi-
dad de tener instalado Excel, únicamente habrı́a que instalar en los equipos donde
vaya a utilizarse el propio controlador. Este puede descargarse desde Microsoft
sin ningún coste y está disponible para distintas versiones de Windows.
NOTA
Según indica Microsoft, fabricante del controlador ODBC para Ex-
cel, las operaciones que es posible llevar a cabo con dicho contro-
lador son limitadas. Básicamente solo se contemplan las consultas
(SELECT) y la adición de nuevos datos (INSERT), pero no el resto de
operaciones (UPDATE o DELETE). Puedes obtener más información bus-
cando el documento INF: Excel ODBC Driver and Text ODBC
Driver Notes en soporte de Microsoft.
6.1.2 Configuración de FireDAC para usar
un controlador ODBC
Para utilizar un controlador ODBC es necesario facilitar una cadena de parámetros
de configuración, especificando cuál es el controlador a usar, el nombre de usuario
y contraseña si procede, la ruta y nombre de la base de datos, etc. Opcional-
mente pueden existir parámetros especı́ficos de cada controlador. Toda esta in-
formación la introducirı́amos, directa o indirectamente, en la propiedad Params
del componente TFDConnection.
En el caso concreto del controlador ODBC para Excel, es importante que se
incluyan tres parámetros adicionales: Mode, ReadOnly y HDR. Con los dos
primeros se establece el modo de apertura del archivo Excel. Habitualmente les
asignaremos los valores ReadWrite y false, indicando ası́ que no se abrirá
solo para lectura. En cuanto al tercer parámetro, también de tipo booleano, su
finalidad es indicar si las hojas del archivo Excel cuentan con una primera fila
conteniendo los nombres de las columnas o no, según lo cual le asignaremos
el valor true o false, respectivamente. Por defecto dicho parámetro toma
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
184 BASES DE DATOS DE ESCRITORIO
el valor false, asumiendo que no existe una cabecera con los nombres de los
campos.
Mediante el parámetro Database facilitaremos al controlador la ubicación
y nombre del archivo Excel con el que queremos trabajar. Dependiendo de la
versión del controlador se permitirá el acceso únicamente al antiguo formato
.xls o también al más reciente .xlsx.
La configuración completa, tal y como la introducirı́amos en la citada propie-
dad Params, serı́a la mostrada en el Listado 6.1.
1 DriverID=ODBC
2 ODBCDriver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, ⤦
Ç *.xlsb)}
3 Database=Ruta\[Link]
4 User_Name=admin
5 ODBCAdvanced=Mode=ReadWrite;ReadOnly=false; HDR=yes
Listado 6.1 Parámetros de configuración ODBC
6.1.3 Consultas sobre un libro Excel
Una vez establecida la conexión con el archivo Excel, el libro que contiene es
visto por el controlador como una base de datos. Cada una de sus hojas serı́a
como una tabla, pero hemos de tener en cuenta que su nombre siempre irá
seguido del sufijo $. Dado que este es un carácter especial, para usarlo es preciso
introducir el nombre entre corchetes. Suponiendo que en el archivo existiese una
hoja llamada Hoja1, una consulta como la mostrada a continuación recuperarı́a
todo su contenido.
1 SELECT *
2 FROM [Hoja1$]
Listado 6.2 Consulta para obtener el contenido de una hoja
La selección de columnas de la hoja se efectuará directamente en caso de
que cuente con una cabecera con los nombres y se haya usado el parámetro
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ACCESO A DATOS EN ARCHIVOS DE MICROSOFT EXCEL 185
HDR=yes en la conexión, como si de una tabla corriente se tratase. En caso
contrario se recurrirı́a a incluir en la propia tabla el rango de celdillas a tomar,
usando la misma sintaxis habitual en Excel. Por ejemplo:
1 SELECT *
2 FROM [Hoja1$A1:B5]
Listado 6.3 Selección de un rango de celdillas
En este ejemplo se recuperarı́a el contenido de cinco filas, 1 a 5, con dos
columnas, A y B. También es posible usar únicamente el nombre de columna
para recuperar todas las filas que contenga. Si la hoja tuviese un encabezado
y se hubiese incluido el parámetro HDR=yes, asumiendo que el nombre de las
columnas fuese Continente y Pais podrı́amos recuperar la misma infor-
mación ası́:
1 SELECT Continente, Pais
2 FROM [Hoja1$]
Listado 6.4 Selección de un rango de celdillas
En las consultas es posible utilizar las cláusulas WHERE, ORDER BY, GROUP
BY, INNER JOIN, etc., ası́ como funciones de agregado de datos. Si el contro-
lador lo permite, también podemos realizar otras operaciones como la inserción
de nuevos datos
6.1.4 Supuesto práctico
Comprobemos con un ejercicio práctico cómo usarı́amos la información almace-
nada en un archivo Excel y cómo agregar nuevos datos al mismo, todo ello desde
un programa Delphi ejecutándose en Windows.
Partiremos de una hoja de cálculo Excel en la que tenemos una página, lla-
mada DatosIniciales, con una lista de datos relativos a la población por
paı́ses de todo el mundo con datos segmentados por sexo y zona, tal y como
se muestra en la Figura 6.1. Cada paı́s podrı́a aparecer varias veces, conte-
niendo cada fila datos parciales de la población. El objetivo es obtener esos
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
186 BASES DE DATOS DE ESCRITORIO
datos en nuestra aplicación, agregarlos de forma que obtengamos la población
de los paı́ses de un continente concreto y, finalmente, agregar esa información
en nueva hoja al archivo Excel.
Figura 6.1 CONTENIDO DE LA HOJA EXCEL
Como puede apreciarse en la Figura 6.1, la hoja cuenta con una primera fila
que actúa como cabecera, asignando un nombre a cada una de las columnas. Esto
nos permitirá referirnos a ellas mediante esos nombres en lugar de como A, B,
etc.
Iniciaremos un nuevo proyecto en Delphi, seleccionando la plantilla en blanco
de la categorı́a M ULTI -D EVICE A PPLICATION. Como es habitual, agregare-
mos al proyecto un módulo de datos y usaremos la opción F ILE —U SE U NIT
para hacer referencia al mismo desde el formulario, separando ası́ los compo-
nentes de acceso a datos de la interfaz de usuario del programa.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ACCESO A DATOS EN ARCHIVOS DE MICROSOFT EXCEL 187
6.1.5 Configuración de la conexión por ODBC
Introducimos en el módulo de datos un componente TFDConnection y hace-
mos doble clic sobre él para abrir el cuadro de diálogo de configuración (véase
la Figura 6.2).
Figura 6.2 CONFIGURACI ÓN DE LA CONEXI ÓN AL ARCHIVO EXCEL
EJEMPLO 6.1 [Link]
Puedes encontrar este proyecto completo en la carpeta MSExcel.
Además del proyecto también se incluye el archivo Excel con los datos.
Para poder ejecutar el programa deberás instalar el controlador ODBC
para Microsoft Excel, si no está en tu sistema, y modificar el parámetro
Database para establecer la ruta donde está el archivo.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
188 BASES DE DATOS DE ESCRITORIO
Seleccionamos de la lista DRIVER ID el controlador ODBC, abriendo a conti-
nuación la lista asociada a la propiedad ODBCDriver para elegir el
controlador correspondiente a Excel. En la propiedad Database facilitamos
la ubicación y nombre del archivo. Finalmente, en la propiedad
ODBCAdvanced establecemos la configuración avanzada descrita
anteriormente, fjando el modo de apertura de la hoja Excel e indicando que
existe una cabecera con los nombres de las columnas.
Finalizada la configuración, podemos usar el botón TEST para comprobar que
es posible abrir el archivo Excel, ası́ como introducir alguna consulta de prueba
en la página SQL SCRIPT, ajustándonos a la sintaxis que se explicó previamente.
6.1.6 Consulta de recuperación de datos
El paso siguiente será añadir al módulo de datos un componente TFDQuery,
abrir el editor asociado e introducir la consulta SQL que queremos ejecutar. Nos
interesa obtener la población de cada paı́s por sexo para todos los paı́ses de un
continente. Dado que cada paı́s puede aparecer más de una vez, usaremos la
función de agregado SUM y la cláusula GROUP BY, tal y como se muestra a
continuación:
1 SELECT Pais, SUM(Hombres) AS TotalHombres, SUM(Mujeres) AS ⤦
Ç TotalMujeres
2 FROM [DatosIniciales$]
3 WHERE Continente = ’Europa’
4 GROUP BY Pais
Listado 6.5 Titulo
Tras escribir la consulta el botón EXECUTE la ejecutará y nos permitirá
comprobar tanto los datos devueltos como la estructura de estos. En este caso,
como se muestra en la Figura 6.3, recuperamos tres columnas, una de tipo
cadena y dos números en punto flotante. Usando la página OPCIONES de la
ventana de parámetros de conexión (Figura 6.2) podrı́amos, en caso necesario,
modificar la asociación entre tipos de datos Excel y tipos Delphi.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ACCESO A DATOS EN ARCHIVOS DE MICROSOFT EXCEL 189
Figura 6.3 CONSULTA PARA OBTENER LOS DATOS DE LA HOJA
Para terminar con el módulo de datos, agregaremos el habitual componente
TFDGUIxWaitCursor y un TFDPhysODBCDriverLink. Opcionalmente
podemos dar el valor True a la propiedad Active del TFDQuery para ver los
datos durante el diseño de la interfaz.
6.1.7 Diseño de la interfaz de usuario
Disponiendo de los elementos que nos permitirán acceder al contenido del archivo
Excel, procedamos ahora a diseñar una sencilla interfaz de usuario que los muestre.
Para ello introduciremos en el formulario los elementos siguientes:
Un control TToolBar ajustado a la parte superior del formulario.
Un TButton que quedará contenido en el anterior. Cambiaremos su pro-
piedad Text asignándole el texto Exportar.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
190 BASES DE DATOS DE ESCRITORIO
Un control TGrid a cuya propiedad Align daremos el valor Client, a
fin de que ocupe el resto del espacio disponible en el formulario.
Usando el L IVE B INDINGS D ESIGNER vincularemos el control TGrid con
el componente TFDQuery, a fin de mostrar el contenido de las tres columnas
resultantes de la consulta. Los enlaces son los mostrados en la Figura 6.4.
Figura 6.4 ENLACE ENTRE LA CUADR ÍCULA Y LOS DATOS
El control Grid cuenta con un editor de columnas, accesible mediante la
opción C OLUMNS E DITOR de su menú contextual, desde el que podemos per-
sonalizar la visualización de las columnas, por ejemplo asignándoles una cabecera
más adecuada en lugar de utilizar los nombres de los campos (véase Figura 6.5).
Figura 6.5 CONFIGURACI ÓN DE LAS COLUMNAS DEL TGR I D
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ACCESO A DATOS EN ARCHIVOS DE MICROSOFT EXCEL 191
Solo con esto ya deberı́amos poder ver la información devuelta por la consulta
en la cuadrı́cula de datos. Podemos comprobarlo dándole temporalmente el valor
True a la propiedad Active del TFDQuery. El resultado deberı́a ser el que
aparece en la Figura 6.6.
Figura 6.6 LA CUADR ÍCULA MOSTRANDO LOS DATOS DE LA HOJA EXCEL
6.1.8 Apertura de la conexión
Un archivo Excel no es una base de datos, razón por la que no puede ser abierto
simultáneamente para escritura por dos o más programas. Este es un factor
importante a tener en cuenta. Si tenemos la hoja abierta en Excel nuestro
programa fallará al ejecutarse. Incluso si tenemos activa la conexión en el
diseñador, al intentar ejecutar el proyecto se producirá una excepción. Por ello
daremos el valor False a la propiedad Active del TFDQuery, controlando
la conexión desde el código del programa.
Concretamente usaremos el evento OnCreate del módulo de datos para ac-
tivar la conexión. Hacemos doble clic sobre el módulo de datos e introducimos
una simple sentencia de asignación, como se muestra en el listado siguiente:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
192 BASES DE DATOS DE ESCRITORIO
1 procedure [Link](Sender: TObject);
2 begin
3 [Link] := True;
4 end;
Listado 6.6 Apertura de la conexión desde el módulo de datos
Dado este paso deberı́amos poder ejecutar el programa y navegar por los datos
sin ningún problema.
6.1.9 Exportación de los datos
La última operación que nos falta por implementar es la exportación de los
datos que estamos viendo en el programa, añadiéndolos como una nueva hoja
al archivo Excel. Esta será la finalidad del botón dispuesto en la parte superior,
por lo que hacemos doble clic sobre él y le asociamos el código facilitado en el
Listado 6.7.
Utilizamos el método ExecSQL del componente TFDConnection para
ejecutar directamente las sentencias SQL apropiadas. Concretamente son dos:
una para crear la nueva hoja en el libro Excel y otra para introducir en ella los
datos que queremos escribir. La primera de las consultas fallará en caso de que
en el libro ya exista una hoja con el mismo nombre. Podrı́amos controlar dicha
excepción y modificar el nombre, por ejemplo agregándole un número detrás.
1 procedure TfrmMain.Button1Click(Sender: TObject);
2 var
3 query: String;
4 begin
5 with [Link] do
6 begin
7 query := ’CREATE TABLE SumEuropa (Pais varchar, Hombres ⤦
Ç integer, Mujeres integer)’;
8 ExecSQL(query);
9
10 query :=
11 ’INSERT INTO [SumEuropa$](Pais, Hombres, Mujeres) ’ +
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
ACCESO A DATOS EN ARCHIVOS DE MICROSOFT EXCEL 193
12 ’SELECT Pais, sum(Hombres) AS TotalHombres, sum(⤦
Ç Mujeres) AS TotalMujeres ’ +
13 ’FROM [DatosIniciales$] ’ +
14 ’WHERE Continente = ’’Europa’’ ’ +
15 ’GROUP BY Pais’;
16 ExecSQL(query);
17 end;
18 end;
Listado 6.7 Código asociado al botón de exportación
Ahora ya estamos en disposición de ejecutar el programa. Este mostrarı́a
(véase la Figura 6.7) la cuadrı́cula con la población por paı́ses, según se es-
pecı́fico en la consulta de recuperación de datos.
Figura 6.7 LA APLICACI ÓN EN FUNCIONAMIENTO
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
194 BASES DE DATOS DE ESCRITORIO
Tras hacer clic en el botón E XPORTAR podemos abrir la hoja de cálculo en
Excel y verificar que, tal y como se muestra en la Figura 6.8, existe una nueva
hoja con los datos introducidos desde la aplicación Delphi.
Figura 6.8 LA HOJA DE DATOS AGREGADA POR LA APLICACI ÓN DELPHI AL LIBRO
EXCEL
NOTA
La técnica descrita en esta sección, usando controladores ODBC,
también nos permitirá acceder a datos alojados en formatos antiguos pero
aún presentes en muchas empresas, como dBase o Paradox. Solamente
tendrı́amos que elegir el controlador ODBC apropiado.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
USO DE DATOS ALMACENADOS EN ARCHIVOS DE TEXTO 195
6.2 Uso de datos almacenados en
archivos de texto
En muchas ocasiones los datos que ha de utilizar una aplicación se encuentran
almacenados en archivos de texto simples. Estos pueden haber sido creados y
ser utilizados directamente por el usuario, con un editor sencillo, o bien ser ge-
nerados por aplicaciones que utilizan formatos más especializados. En cualquier
caso nos interesará saber cómo podemos ejecutar consultas sobre esos datos para
utilizarlos en un proyecto propio.
Los archivos de texto se estructuran en lı́neas, al igual que una hoja de cálculo
lo hace en filas o una base de datos en registros. Por regla general existe un
carácter de retorno de carro que marca el final de cada lı́nea. Para diferenciar
los campos existentes en cada lı́nea suele utilizarse un separador concreto, como
pueden ser tabuladores, comas o puntos y comas1 . Dicho separador no debe
aparecer en el interior de un dato. Para evitar confusiones, es posible entre-
comillar aquellos campos que sean cadenas de texto. También es importante
determinar cuál será el separador de miles si existen datos numéricos con parte
no entera.
Aunque podrı́amos utilizar un controlador ODBC u OLEDB para acceder al
contenido de un archivo de texto, la operaciones que podemos efectuar sobre
ellos son, en general, limitadas. En esta sección aprenderemos a conectar una
interfaz de usuario Delphi con el contenido de un archivo CSV de forma directa,
sin usar más que algunos componentes FireDAC.
6.2.1 Lectura de archivos CSV con FireDAC
Lo primero que necesitamos saber es cómo podemos leer el contenido de un
archivo de texto, por ejemplo en formato CSV, manteniendo la información en
un componente sobre el que podamos realizar consultas y otras operaciones.
FireDAC nos ofrece un mecanismo genérico, representado por el compo-
nente TFDBatchMove, para leer datos de un origen y escribirlos en un des-
1
Uno de los formatos de archivos de texto más conocido es el CSV (Comma Separated
Values), denominado ası́ porque cada dato se separa del siguiente por una coma.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
196 BASES DE DATOS DE ESCRITORIO
tino. Tanto origen como destino pueden ser archivos de texto, componentes que
alojan conjuntos de datos (como un TFDQuery) o conexiones con RDBMS.
En la página F IRE DACT ETL de la Paleta de componentes (véase la Figura
6.9) encontraremos tanto el componente TFDBatchMove como los compo-
nentes encargados de leer y escribir los datos para cada categorı́a. Ası́ tenemos
un TFDBatchMoveTextReader y un TFDBatchMoveTextWriter, para
trabajar sobre archivos de texto; un TFDBatchMoveDataSetReader y un
TFDBatchMoveDataSetWriter, para leer y escribir de componentes que
representan conjuntos de datos, y finalmente un TFDBatchMoveSQLReader
y un TFDBatchMoveSQLWriter, encargados de la lectura y escritura en co-
nexiones con bases de datos.
Figura 6.9 COMPONENTES FIREDAC PARA TRANSFERIR DATOS ENTRE ORIGEN Y
DESTINO
Cada uno de estos componente contendrı́a la configuración del origen o el des-
tino de la transferencia de datos, encargándose el TFDBatchMove de realizar
las conversiones necesarias para trasladar la información de un punto a otro. El
componente TFDBatchMove dispone de las propiedades Reader y Writer,
a las que se conectarı́a el objeto que actuará de lector y el que operará como es-
critor, respectivamente. La transferencia se completará mediante una invocación
al método Execute.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
USO DE DATOS ALMACENADOS EN ARCHIVOS DE TEXTO 197
La configuración general para llevar a cabo un proceso de transferencia de
datos con TFDBatchMove es el representado esquemáticamente en la Figura
6.10. El citado componente se comunica bidireccionalmente con el lector y el
escritor. Estos usan su configuración especı́fica para llevar a cabo la lectura, en
este ejemplo de un archivo CSV, y la escritura, por ejemplo en un TFDQuery.
Figura 6.10 PROCESO DE TRANSFERENCIA DE DATOS CON TBA T C HMO V E
6.2.2 Procesamiento local de consultas SQL
Para conectar una interfaz de usuario Delphi a un origen de datos necesitamos
que la información esté alojada en algún componente derivado de TDataSet,
como puede ser TFDQuery. Estos componentes se vinculan a un componente
de conexión, un TFDConnection, que en último término es el encargado de
enviar las consultas al gestor de datos para que se ejecuten.
En los capı́tulos previos hemos trabajado con Microsoft Access, SQLite e
InterBase, todos ellos con capacidad para evaluar y ejecutar sentencias SQL.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
198 BASES DE DATOS DE ESCRITORIO
Incluso en el caso de Excel, según comprobamos en la sección previa de este
mismo capı́tulo, el controlador ODBC es capaz de interpretar un subconjunto
bastante amplio de SQL. Al trabajar con información procedente de un archivo
de texto, sin embargo, no existe ningún software en el que los componentes
FireDAC deleguen esa tarea, por lo que es preciso contar con algún mecanismo
que se encargue del procesamiento de las sentencias SQL.
FireDAC puede usar el motor de SQLite para procesar consultas SQL sin
necesidad de conectar con base de datos alguna. Para ello se utilizan dos
componentes:
TFDConnection: Se configura para que utilice el controlador de SQLite,
pero sin asignar valor alguno a la propiedad Database. De esta manera
no se creará ningún archivo en disco.
TFDLocalSQL: Conectado al anterior, este componente se encarga de proce-
sar localmente las consultas SQL recibidas, utilizando para ello el motor de
SQLite.
Cualquier componente conectado al TFDConnection podrá utilizar la ca-
pacidad de procesamiento local del TFDLocalSQL. Por ejemplo, al conectar un
TFDQuery y ejecutar una consulta será el TFDLocalSQL el que la interprete,
determinando de dónde se extraerá la información, cómo se filtrarán las filas y
proyectarán las columnas, etc.
La información sobre la que trabajarán los componentes TFDLocalSQL y
TFDConnection puede tener una representación estática, estableciéndose en
la fase de diseño cuáles son los componentes en que reside. Para ello se utilizarı́a
la propiedad DataSets del TFDLocalSQL. También es posible generar la
información dinámicamente, por ejemplo a través de un TFDBatchMove,
respondiendo a los eventos del componente TFDLocalSQL.
El evento OnGetDataSet del componente TFDLocalSQL se genera si,
al procesar una consulta, se hace referencia a un conjunto de datos (una tabla
o una vista) no disponible en la propiedad DataSets. El método asociado a
dicho evento aporta el nombre del conjunto de datos, que puede ser utilizado para
prepararlo y devolverlo como resultado. Los parámetros ADataSet y AOwned,
recibidos por referencia en dicho evento, permiten asignar el conjunto de datos e
indicar si este ha de ser gestionado por el TFDLocalSQL.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
USO DE DATOS ALMACENADOS EN ARCHIVOS DE TEXTO 199
6.2.3 Consultas sobre archivos CSV
Comprobemos, mediante el desarrollo de un caso práctico, cómo podemos efec-
tuar consultas sobre los datos contenidos en un archivo CSV usando los compo-
nentes enumerados en los apartados previos.
EJEMPLO 6.2 [Link]
Puedes encontrar este proyecto completo en la carpeta DatosCSV.
Además del proyecto también se incluyen dos archivos CSV con datos:
[Link] y [Link]. Tanto estos como cualquier otro archivo
CSV pueden ser usados en las consultas, siempre que se alojen en la car-
peta apropiada. Tendrás que modificar la ubicación de esta en el método
asociado al evento OnGetDataSet del componente TFDLocalSQL
(en el módulo de datos).
Partiremos, como es habitual, creando un nuevo proyecto vacı́o de tipo M ULTI -
D EVICE A PPLICATION y agregando un módulo de datos al mismo. No debe-
mos olvidar agregar al formulario una referencia al módulo de datos. En los
apartados siguientes se describen los pasos que hemos de reproducir.
6.2.4 Componentes de conexión y proce-
samiento de consultas
Comencemos introduciendo en el módulo de datos los componentes de conexión
y procesamiento de las consultas. Serán tres componentes: un TFDConnection,
un TFDLocalSQL y un TFDQuery. Si los añadimos en ese orden, los dos
últimos se enlazarán automáticamente con el primero.
Del TFDConnection cambiaremos la propiedad DriverName, seleccio-
nando SQLite de la lista de valores posibles, y daremos el valor False a
la propiedad LoginPrompt. Con esta configuración el TFDConnection
delegará la ejecución de las consultas SQL en el TFDLocalSQL conectado
a él. De los otros dos componentes solamente establecerı́amos la propiedad
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
200 BASES DE DATOS DE ESCRITORIO
Connection, en caso de que se no se hubiese creado automáticamente el en-
lace con el TFDConnection.
También agregaremos al módulo un componente TFDGUIxWaitCursor y
un TFDPhysSQLiteDriverLink, introduciendo ası́ en el código las refe-
rencias necesarias para incorporar el controlador de SQLite.
6.2.5 Lectura de los datos CSV
Nuestro objetivo es conectar la interfaz de usuario al componente TFDQuery,
permitiendo ejecutar distintas consultas a través de él obteniendo datos de ar-
chivos CSV. Sin embargo, si en este momento introdujésemos una consulta en
la propiedad SQL del TFDQuery y le diéramos el valor True a su propiedad
Active el resultado sería un error. El TFDConnection no está realmente
conectado a una base de datos y el TFDLocalSQL no encontraría la tabla
solicitada.
Para leer los datos del archivo CSV adecuado, entregándoselos al compo-
nente TFDLocalSQL que, a su vez, los facilitarı́a al TFDQuery, tendremos
que añadir varios componentes más al módulo de datos, tal y como se aprecia en
la Figura 6.11. Vamos a ir abordando su configuración paso a paso.
El primer componente a insertar es el TFDBatchMove, encargado de ges-
tionar el proceso de lectura del archivo CSV y la transferencia de los datos a un
derivado de TDataSet. Al inicio de dicho proceso es posible llevar a cabo una
exploración de las primeras filas de datos a fin de determinar su es tructura. Este
comportamiento lo controla la propiedad Analyze que, de no estar vacı́a, invo-
cará al método GuessFormat de TFDBatchMove para deducir si existe o no
una cabecera, el separador de campos, etc., dependiendo de las opciones que se
hayan activado (véase la Figura 6.12).
NOTA
El método GuessFormat únicamente se utiliza cuando la
transferencia de datos implica a un origen que no contiene metadatos,
como es el caso de los archivos de datos. Si se usase un origen con
metadatos estos describirían la estructura de la información, no
necesitándose el proceso mencionado.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
USO DE DATOS ALMACENADOS EN ARCHIVOS DE TEXTO 201
Figura 6.11 COMPONENTES A INTRODUCIR EN EL M ÓDULO DE DATOS
Figura 6.12 CONFIGURACI ÓN DEL TFDBA T C HMO V E
A continuación añadiremos un componente TFDBatchMoveTextReader.
Este se enlazará automáticamente con el anterior. Si conocemos la estructura de
los archivos con los que vamos a trabajar, en este caso se trata de archivos CSV,
podemos usar las propiedades Separator, Delimiter y FormatSettings
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
202 BASES DE DATOS DE ESCRITORIO
para configurar el proceso de lectura2 . Esta última propiedad determina cuáles
serán los separadores decimales, de fechas, de miles, sı́mbolos de moneda y otros
parámetros.
En nuestro caso indicaremos que el separador de campos, asignado a la pro-
piedad Delimiter (véase la Figura 6.13), es la coma y que el separador de
parte decimal, propiedad [Link], es el
punto. Si fuésemos a usar siempre el mismo archivo CSV podrı́amos asignar su
ubicación y nombre a la propiedad FileName durante la fase de diseño, pero
en nuestro ejercicio ese es un parámetro que no conoceremos hasta que vaya a
ejecutarse una consulta.
Figura 6.13 CONFIGURACI ÓN DEL COMPONENTE TFDBA T C HMO V ETE X TRE A D E R
El paso siguiente será introducir en el módulo de datos un componente
TFD-BatchMoveDataSetWriter, que se encargará de guardar los datos
leı́dos del archivo CSV en un conjunto de datos, y un componente
TFDMemTable, cuyo objeto será servir como almacén temporal de esos datos,
durante la transferencia.
2
El componente TFDBatchMoveTextReader es genérico, no especı́fico para archi-
vos CSV, pudiendo leer prácticamente cualquier archivo de texto que use unos separadores
concretos para lı́neas, campos, etc.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
USO DE DATOS ALMACENADOS EN ARCHIVOS DE TEXTO 203
En este momento tenemos en el módulo de datos todos los elementos que
necesitamos para poder leer el contenido de una archivo CSV, transferirlo al
TFDMemTable y, desde ahı́, entregarlo al TFDLocalSQL para que lo intro-
duzca en el TFDQuery. La secuencia de eventos serı́a la siguiente:
1. Desde la interfaz del programa se introduce una consulta en la propiedad
SQL del TFDQuery y se llama al método Open o se da el valor True a la
propiedad Active.
2. El TFDQuery recurre al TFDConnection al que apunta su propiedad
Connection para ejecutar la consulta y obtener el conjunto de datos re-
sultante.
3. La consulta pasa del TFDConnection al motor de procesamiento local
del componente TFDLocalSQL. Este no dispone de la tabla referenciada
en la consulta en su propiedad DataSets, por lo que genera el evento
OnGetDataSet.
4. En el método asociado a dicho evento introduciremos el código para leer el
archivo CSV y transferir los datos al TFDMemTable, usando para ello los
componentes que hemos agregado antes.
5. Asignaremos al parámetro ADataSet que se recibe en dicho método el
contenido del TFDMemTable, conteniendo ya la información del archivo
CSV.
6. El componente TFDLocalSQL entregará el resultado de la consulta de
vuelta al TDDQuery que, a su vez, la facilitará a los controles de la interfaz
de usuario.
El código indicado en el paso 4 será el mostrado en el Listado 6.8. El parámetro
AName es el nombre de la tabla que aparece en la consulta, nombre que usare-
mos para abrir el archivo CSV y ejecutar la conversión.
1 procedure TdmIris.FDLocalSQL1GetDataSet(ASender: TObject;
2 const ASchemaName, AName: string;
3 var ADataSet: TDataSet; var AOwned: Boolean);
4 begin
5 try
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
204 BASES DE DATOS DE ESCRITORIO
6 [Link];
7 [Link] := ’DatosCSV\’ + AName + ’.csv’;
8 [Link];
9 ADataSet := IrisMemTable;
10 AOwned := True;
11 except on E: Exception do
12 ShowMessage([Link]);
13 end;
14 end;
Listado 6.8 Transferencia de datos CSV al TFDMemTable
6.2.6 Diseño de la interfaz
Nuestra interfaz de usuario estará basada una vez más en un componente TGrid
que, mediante LiveBindings, vincularemos con el TFDQuery del módulo de
datos. Además también dispondremos un TToolBar en la parte superior que
servirá de contenedor de un TEdit y un TButton. En el TEdit podemos
introducir en la propiedad Text una consulta de ejemplo, como se muestra en
la Figura 6.14.
Cada vez que se haga clic en el TButton cerraremos la consulta actual, visi-
ble en el TGrid, y procederemos a ejecutar la que se hubiese introducido en el
TEdit. El código necesario para ello es el mostrado a continuación:
1 procedure TfrmMain.Button1Click(Sender: TObject);
2 begin
3 with [Link] do
4 begin
5 Close;
6 [Link];
7 [Link]([Link]);
8 Open;
9 end;
10 end;
Listado 6.9 Código asociado al botón que ejecutará la consulta
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
USO DE DATOS ALMACENADOS EN ARCHIVOS DE TEXTO 205
Figura 6.14 ASPECTO DE LA INTERFAZ EN EL DISE ÑADOR DE FORMULARIOS
Con esto ya tenemos el programa terminado. Podemos ejecutarlo y probar
distintas consultas (véase la Figura 6.15) sobre los archivos CSV de ejemplo o
cualesquiera otros que dispongamos en la misma carpeta.
Figura 6.15 EL PROGRAMA MOSTRANDO DATOS DE DOS ARCHIVOS CSV
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
206 BASES DE DATOS DE ESCRITORIO
A pesar de que estemos trabajando con información alojada en un archivo de
texto, las consultas pueden usar filtros, agrupaciones e incluso relaciones entre
tablas, por ejemplo de tipo maestro/detalle en caso de que tuviésemos un archivo
CSV con los datos maestros y otra con los de detalle.
NOTA
La información accesible mediante la interfaz de usuario de este pro-
grama podrı́a modificarse, pero los cambios quedarı́an almacenados en el
TFDQuery y no llegarı́an a transferirse a los archivos CSV de origen.
Para ello tendrı́amos que utilizar un conjunto adicional de componentes
TFDBatchMove, con una configuración inversa a la que hemos empleado
para la lectura. Al igual que la lectura, la escritura del contenido actual
del TFDQuery podrı́a realizarse a demanda, con un segundo botón que
escribiese los cambios.
6.3 Resumen
En este capı́tulo hemos aprendido a utilizar desde nuestras aplicaciones Delphi
otros orı́genes de datos de uso habitual en sistemas de escritorio, completando
ası́ el recorrido por las distintas configuraciones de acceso a datos de capı́tulos
previos.
Primero se ha descrito el procedimiento a seguir para, mediante un contro-
lador ODBC, acceder a información almacenada en hojas de cálculo Excel, ası́
como para agregar a las mismas nueva información. Usando controladores ODBC
podrı́amos también operar sobre otros tipos de bases de datos de escritorio, como
dBase o Paradox, aunque estos formatos son cada vez menos habituales.
En la segunda parte del capı́tulo hemos entrado en contacto con un conjunto de
componentes totalmente nuevo, como son los destinados a transferir datos entre
distintas fuentes, la familia de componentes TFDBatchMoveXXX, y también
los que facilitan el trabajo con datos cuando no existe una conexión real con
un motor externo que los gestione, como TFDLocalSQL y TFDMemTable.
Hemos aprendido a usar estos componentes con un objetivo concreto: usar en
una aplicación Delphi información almacenada en archivos en formato CSV.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
RESUMEN 207
El próximo capı́tulo nos servirá para profundizar en el uso de algunos de los
componentes introducidos en este. El objetivo será mostrar cómo una aplicación
puede trabajar sobre datos que no se almacenan en archivos, sino que residen
únicamente en memoria durante la ejecución.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Capı́tulo 7
BASES DE DATOS EN
MEMORIA CON FIREDAC
No todas las aplicaciones que manejan datos durante su ejecución necesitan leer-
los de un archivo u obtenerlos de una conexión a un RDBMS, ni posiblemente
tampoco precisen almacenarlos al terminar la tarea. Hay muchas situaciones,
especialmente cuando se utilizan dispositivos móviles, en las que los datos van
generándose a lo largo de la ejecución, obtenidos de sensores integrados en el
dispositivo, de una conexión a algún servicio u otro tipo de actividad.
En estos casos lo que necesita la aplicación es un almacenamiento temporal
para la información, estableciendo su estructura al inicio y descartando los datos
al terminar.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
210 BASES DE DATOS EN MEMORIA
Esto no significa que no sea posible conservar estos datos para un uso poste-
rior, en caso de que el usuario lo demandase. Para ello podrı́an utilizarse archivos
en diferentes formatos, según las necesidades.
El objetivo de este capı́tulo es mostrarnos los procedimientos a seguir para
desarrollar aplicaciones que trabajan con bases de datos en memoria, sin una
conexión permanente a un gestor de datos, como podrı́a ser InterBase o Access
en el escritorio, y sin que sea imprescindible utilizar archivos en almacenamiento
externo.
7.1 El motor local de SQL de FireDAC
FireDAC dispone de un componente llamado TFDLocalSQL, lo conocı́amos
en la segunda parte del anterior capı́tulo, que actúa como un motor local de
procesamiento de consultas SQL. Conjuntamente con un TFDConnection,
cuando el controlador elegido es SQLite y la propiedad Database se deja en
blanco o se le asigna el valor especial :memory:, lo que obtenemos es una base
de datos en memoria, tanto el gestor de almacenamiento de datos como el motor
de procesamiento de consultas que actúa sobre él.
Al no estar conectados a una verdadera base de datos, o algún controlador que
haga aparecer como tal un origen de otro tipo (como ocurre con ODBC y Excel),
la meta-información que describe la estructura de la información no puede ser
obtenida automáticamente. Básicamente tendremos tres alternativas para definir
estas estructuras:
Mediante consultas SQL de tipo DDL (Data Definition Language), usando
sentencias del tipo CREATE TABLE.
Usando las propiedades y métodos de algún derivado de TFDDataSet para
definir sus columnas.
Copiando esa información desde algún conjunto de datos al que tengamos
acceso.
La base de datos en memoria puede mantener la meta-información de una
base de datos completa, no solo de una tabla aislada. Es posible, por tanto,
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONJUNTOS DE DATOS EN MEMORIA 211
definir varias tablas y establecer relaciones entre ellas, como harı́amos con una
base de datos estándar, ası́ como definir vistas y otros objetos. Estos podrı́an
conectarse después a componentes que representarı́an los distintos conjuntos de
datos en memoria.
7.2 Conjuntos de datos en memoria
Otro de los componentes introducidos en el capı́tulo previo fue TFDMemTable,
usado como almacenamiento temporal para realizar la conversión de datos CSV a
un conjunto de datos. Dicho componente, como su propio nombre denota, ofrece
la funcionalidad necesaria para mantener un conjunto de datos en memoria, con
independencia de cómo haya sido generado.
La estructura del conjunto de datos alojado en un TFDMemTable, la lista de
columnas que lo componen, sus nombres y tipos de datos, pueden ser definidos
manualmente, usando para ello el Editor de columnas al que da paso la opción
F IELDS E DITOR de su menú contextual (véase la Figura 7.1).
Figura 7.1 O PCIONES EN EL MEN Ú CONTEXTUAL DE UN TFDM E M T A B L E .
También es posible recuperar esa información de un archivo XML, con la
opción L OAD F ROM F ILE, ası́ como copiarla desde otro conjunto de datos que
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
212 BASES DE DATOS EN MEMORIA
tengamos en el mismo contenedor, mediante la opción A SSIGN DATA S ET. Una
alternativa más serı́a la definición de las columnas mediante código.
Además de la estructura y los datos propiamente dichos, un TFDMemTable
también incorpora la funcionalidad necesaria para conservar un registro de los
cambios introducidos en los datos, pudiendo convertirlos en las sentencias de
actualización apropiadas. En esencia, por tanto, tenemos todo lo necesario para
trabajar sobre un conjunto de datos, con la excepción del mecanismo que per-
mite obtenerlo de una fuente externa. Esto es lo que aportan componentes como
TFDTable, TFDQuery y TFDStoredProc, que son tres versiones especiali-
zadas de TFDMemTable con capacidad para recuperar la información de estruc-
tura y contenido de una tabla, del resultado de una consulta SQL o del resultado
de la ejecución de un procedimiento almacenado, respectivamente.
Los tres componentes citados usan internamente un TFDMemTable, por lo
que la funcionalidad aportada por este está igualmente presente en todos ellos.
Esto significa que a la hora de trabajar con datos en memoria podemos utilizar
indistintamente uno u otro, según nuestras necesidades.
7.3 Definición de estructuras de datos
en memoria
Para poder trabajar con una base de datos en memoria lo primero que tendremos
que hacer será definir la estructura de cada una de las tablas que necesitemos.
Con este fin podemos recurrir a diferentes opciones, según el tipo de componente
que empleemos.
Si optamos por definir la estructura de las tablas durante la fase de diseño,
que es la primera alternativa que va a describirse, habitualmente utilizaremos
un componente TFDMemTable ya que este cuenta con opciones adicionales no
presentes en TFDQuery o TFDTable, por ejemplo. El procedimiento básico,
no obstante, es exactamente el mismo para los tres componentes.
La definición de la estructura de las tablas durante la ejecución, segundo en-
foque que abordaremos más adelante, puede efectuarse con cualquiera de los
componentes citados ya que, internamente, todos ellos tienen un TFDMemTable,
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
DEFINICIÓN DE ESTRUCTURAS DE DATOS EN MEMORIA 213
disponiendo en consecuencia de un conjunto común de propiedades y métodos
que después TFDQuery y TFDTable extienden con miembros a medida.
7.3.1 En la fase de diseño
Los tres componentes antes citados ofrecen en su menú contextual una misma
opción, F IELDS E DITOR, que da paso a un editor que ya conocemos de capı́tulos
previos. En su momento lo usábamos para seleccionar las columnas de una tabla
que querı́amos incluir en una consulta. Ahora lo utilizaremos para definir las
columnas de una tabla que aún no existe.
Figura 7.2 D EFINICI ÓN DE COLUMNAS DE UNA TABLA CON EL E DITOR DE CAMPOS .
El procedimiento a seguir es siempre el mismo. Una vez abierto el editor de
columnas reproducimos los pasos indicados a continuación:
1. Pulsamos C ONTROL +N (o elegimos la opción N EW F IELD del menú con-
textual del editor) para agregar una nueva columna a la tabla.
2. Se abre un cuadro de diálogo, en el que especificaremos el nombre del
campo, su tipo y su longitud.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
214 BASES DE DATOS EN MEMORIA
3. Mediante el Inspector de objetos ajustamos cualquier otra caracterı́stica del
campo seleccionado en el editor (véase la Figura 7.2).
Una vez que hayamos definido las columnas del conjunto de datos que quere-
mos usar, daremos el valor True a la propiedad Active del componente para
crearlo. Esa acción creará el conjunto de datos en memoria, dejándolo preparado
para su uso como cualquier otro conjunto de datos que hubiésemos obtenido de
una base de datos.
Si el componente que estamos utilizando es un TFDMemTable, la creación
del conjunto de datos se traducirá en la aparición de opciones adicionales en el
menú contextual del componente. En la Figura 7.3, que muestra dicho menú,
puede apreciarse la presencia de las opciones C LEAR DATA y S AVE T O F ILE.
Figura 7.3 OPCIONES EN EL TFDME MTA B L E TRAS HABER GENERADO EL CONJUNTO
DE DATOS
La primera opción eliminarı́a los datos contenidos en el componente, pero
sin eliminar los datos de estructura. Con la segunda se almacenarı́a toda la in-
formación, tanto estructura de la tabla como su posible contenido, en un archivo
XML. El formato de dicho archivo es el mostrado en el Listado 7.1. Su conte-
nido podrı́a ser recuperado con LOAD FROM FILE, ya sea del mismo
componente o de otro distinto, pudiendo leerse durante la ejecución, con una
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
DEFINICIÓN DE ESTRUCTURAS DE DATOS EN MEMORIA 215
llamada al método LoadFromFile. Este es heredado por todos los derivados
de TFDDataSet, entre los que se encuentran TFDMemTable, TFDTable y
TFDQuery.
1 <?xml version="1.0" encoding="utf-8"?>
2 <FDBS Version="14">
3 <Manager UpdatesRegistry="True">
4 <TableList>
5 <Table Name="RastroTable" SourceName="Table" TabID="0" ⤦
Ç EnforceConstraints="False" MinimumCapacity="50" ⤦
Ç CheckNotNull="False">
6 <ColumnList>
7 <Column Name="Lugar" SourceName="Lugar" SourceID="1" ⤦
Ç DataType="Int32" Searchable="True" AllowNull="True⤦
Ç " Base="True" OAllowNull="True" OInUpdate="True" ⤦
Ç OInWhere="True" OriginColName="Lugar"/>
8 <Column Name="TimeStamp" SourceName="TimeStamp" SourceID⤦
Ç ="2" DataType="DateTime" Searchable="True" ⤦
Ç AllowNull="True" Base="True" OAllowNull="True" ⤦
Ç OInUpdate="True" OInWhere="True" OriginColName="⤦
Ç TimeStamp"/>
9 <Column Name="Coords" SourceName="Coords" SourceID="3" ⤦
Ç DataType="AnsiString" Size="18" Searchable="True" ⤦
Ç AllowNull="True" Base="True" OAllowNull="True" ⤦
Ç OInUpdate="True" OInWhere="True" OriginColName="⤦
Ç Coords" SourceSize="18"/>
10 <Column Name="Altitud" SourceName="Altitud" SourceID="4"⤦
Ç DataType="Double" Searchable="True" AllowNull="⤦
Ç True" Base="True" OAllowNull="True" OInUpdate="⤦
Ç True" OInWhere="True" OriginColName="Altitud"/>
11 <Column Name="Comentario" SourceName="Comentario" ⤦
Ç SourceID="5" DataType="AnsiString" Size="50" ⤦
Ç Searchable="True" AllowNull="True" Base="True" ⤦
Ç OAllowNull="True" OInUpdate="True" OInWhere="True"⤦
Ç OriginColName="Comentario" SourceSize="50"/>
12 </ColumnList>
13 <ConstraintList/>
14 <ViewList/>
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
216 BASES DE DATOS EN MEMORIA
15 <RowList/>
16 </Table>
17 </TableList>
18 <RelationList/>
19 <UpdatesJournal>
20 <Changes/>
21 </UpdatesJournal>
22 </Manager>
23 </FDBS>
Listado 7.1 Archivo XML con el contenido del TFDMemTable
Podemos, por tanto, definir la estructura de las tablas de nuestra base de datos
en memoria durante la fase de diseño, usando tantos TFDMemTable como nece-
sitemos y estableciendo las relaciones que correspondan entre ellos, ası́ como
conectar esos componentes con la interfaz de usuario. De esta forma tendrı́amos
un programa preparado para almacenar información sin estar conectado a una
base de datos ni utilizar más archivos que el propio ejecutable.
NOTA
Para que el contenido de un TFDMemTable creado según el procedi-
miento anterior estuviese disponible a través del motor de consultas SQL
local, el componente TFDLocalSQL, tendremos que vincular al primero
con el segundo. Para ello podemos usar la propiedad LocalSQL del
TFDMemTable o bien la propiedad DataSets del TFDLocalSQL.
7.3.2 Durante la ejecución
Si lo preferimos, podemos crear la estructura de nuestra base de datos en memo-
ria durante la propia ejecución del programa, en lugar de hacerlo en la fase de
diseño. En ese caso contamos también con varias alternativas, entre ellas: usar
las propiedades y métodos del componente TFDMemTable, TFDTable o
TFDQuery, o bien trabajar directamente sobre el motor local de consultas SQL
usando sentencias DDL.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
DEFINICIÓN DE ESTRUCTURAS DE DATOS EN MEMORIA 217
La colección FieldDefs
Los citados componentes cuentan con una propiedad, llamada FieldDefs, que
contiene una colección de objetos con la definición de cada una de las colum-
nas del conjunto de datos. Es posible agregar elementos a dicha colección me-
diante el método Add, al que debemos facilitar dos parámetros: el nombre de
la columna y su tipo. Opcionalmente también puede facilitarse un tamaño y
un valor booleano indicando si el campo ha de contener obligatoriamente un
valor. De esta manera es posible definir las columnas que se precisen, tras lo
cual usarı́amos el método CreateDataSet para, efectivamente, crear el con-
junto de datos usando las definiciones introducidas en FieldDefs.
Suponiendo que tuviésemos en nuestro módulo de datos o formulario un
componente llamado FDTable1, con el código mostrado en el Listado 7.2
definirı́amos una tabla con cinco columnas, la crearı́amos y, finalmente, la en-
lazarı́amos con el TFDLocalSQL para poder usarla mediante el motor local de
SQL.
1 with FDTable1 do
2 begin
3 [Link](’Lugar’, ftInteger);
4 [Link](’TimeStamp’, ftDateTime);
5 [Link](’Coords’, ftString, 18);
6 [Link](’Altitud’, ftFloat);
7 [Link](’Comentario’, ftString, 40);
8
9 CreateDataSet;
10
11 [Link](FDTable1);
12 end;
Listado 7.2 Creación de una tabla en ejecución
En caso de que tuviésemos la información sobre la estructura de la tabla en
un archivo XML, como el antes mostrado en el Listado 7.1, podrı́amos usar
el método LoadFromFile del componente para cargar la estructura y, si los
hubiese, también los datos iniciales. En este caso el procedimiento de creación
implementado en el Listado 7.2 quedarı́a reducido a una única sentencia del tipo
[Link](’[Link]’).
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
218 BASES DE DATOS EN MEMORIA
NOTA
Además de definir la estructura del conjunto de datos, también
podrı́amos introducir información inicial en el mismo. Para ello, tras la
llamada a CreateDataSet, usarı́amos el método AppendRecord fa-
cilitando el conjunto de valores a agregar.
Creación de estructuras mediante sentencias DDL
El método alternativo para definir la estructura de una base de datos en memo-
ria durante la ejecución del programa, sin necesidad de agregar componentes
como TFDMemTable, TFDTable o TFDQuery, consiste en utilizar senten-
cias SQL de definición de datos. Estas sentencias se enviarán directamente al
TFDConnection, mediante el método ExecSQL, encargándose el motor lo-
cal de procesamiento de consultas de su ejecución y, como resultado, la creación
de la tabla, vista u otro objeto que se quiera definir.
Además de sentencias DDL para definir estructuras, también podemos usar
el método ExecSQL para introducir cualquier contenido inicial que deban con-
tener las tablas. Por ejemplo:
1 [Link](
2 ’CREATE TABLE Lugares (Codigo INT PRIMARY KEY, Nombre ⤦
Ç TEXT)’);
3
4 [Link](
5 ’INSERT INTO Lugares VALUES (1, "Jaén")’);
Listado 7.3 Creación de una tabla en memoria e inserción de datos
Siempre que el TFDConnection estuviese conectado a un componente
TFDLocalSQL, el contenido generado de esta forma será accesible a través
de componentes TFDTable y TFDQuery. No tenemos más que enlazarlos
al mismo TFDConnection y seleccionar la tabla o introducir la consulta ha-
ciendo referencia a la tabla. Esos componentes, a su vez, serı́an los que en-
lazarı́amos con la interfaz de usuario de la aplicación.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CASO PRÁCTICO 219
Obtención de la estructura desde otro conjunto de datos
La tercera opción que tenemos a nuestro alcance, a la hora de definir la estructura
de una base de datos en memoria, consiste en copiar la estructura de conjuntos de
datos ya existentes. Esto implica que deberı́amos contar con algún componente
conectado a una base de datos, desde la que obtendrı́a su contenido. Suponiendo
que fuese un TFDQuery con el resultado de una consulta, podrı́amos transferir
todo su contenido, tanto estructura como datos, a un TFDMemTable, usando
el método CopyDataSet. A continuación se muestra un ejemplo de cómo lo
harı́amos:
1 [Link](FDQuery1, [coStructure, coRestart, ⤦
Ç coAppend]);
Listado 7.4 Titulo
El segundo parámetro de este método determina qué se copia: coStructure
hace referencia a la estructura y coAppend a que los datos se agregarán también
al objeto FDMemTable1. La opción coRestart indica al método que antes
de iniciar la copia debe colocar el cursor de lectura al inicio del FDQuery1,
obteniendo ası́ todo su contenido.
7.4 Caso práctico
Ahora que ya conocemos las distintas vı́as que podemos seguir para crear una
base de datos en memoria y trabajar con ella, pongamos ese conocimiento en
práctica desarrollando un nuevo proyecto. Este serı́a el de una aplicación que
hipotéticamente irá registrando de forma automática y periódica las coordenadas
en que nos encontramos, para lo cual recurrirı́a al sensor integrado en la mayorı́a
de teléfonos móviles y tabletas. Además de mostrar esa información a medida
que la registra, el programa debe permitir al usuario introducir un comentario, ası́
como manipular las entradas generadas y ejecutar consultas sobre ellas. Todos
los datos estarán alojados exclusivamente en memoria.
Creamos un nuevo proyecto vacı́o de tipo M ULTI -D EVICE A PPLICATION,
lo cual nos permitirı́a desplegarlo en dispositivos móviles, y le agregamos un
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
220 BASES DE DATOS EN MEMORIA
módulo de datos. Enlazamos ambos elementos, como es habitual, para que desde
el formulario podamos acceder a los componentes de datos. A partir de aquı́
iremos dando los pasos descritos en los siguientes apartados.
EJEMPLO 7.1 [Link]
Puedes encontrar este proyecto completo en la carpeta BDDMemoria.
No se precisa configuración adicional para poder utilizarlo ya que los
datos residen en memoria.
7.4.1 Configuración de los componentes de
datos
Introducimos en el módulo de datos del proyecto los componentes indicados a
continuación:
TFDConnection: Tras añadirlo usamos el Inspector de objetos para mo-
dificar sus propiedades DriverName, seleccionando SQLite de la lista
desplegable, y LoginPrompt, a la que daremos el valor False.
TFDLocalSQL: No tenemos más que insertarlo en el formulario y su
propiedad Connection debería vincularlo automáticamente con el
componente anterior.
TFDTable: Al igual que el anterior, se enlazará automáticamente con el
TFDConnection. Lo utilizaremos para definir la estructura de una tabla
en memoria. Únicamente modificaremos su propiedad TableName, a la
que asignaremos el valor Rastro. Este será el nombre que tenga la tabla
en nuestra base de datos en memoria.
TFDQuery: Su propiedad Connection también le enlazará con
el componente TFDConnection. Nos servirá para ejecutar
consultas arbitrarias sobre la base de datos en memoria. No tenemos que
modificar ninguna de sus propiedades.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CASO PRÁCTICO 221
TFDGUIxWaitCursor: Como ya sabemos, este componente es necesario
en cualquier aplicación que utilice FireDAC.
Pretendemos crear la estructura de la base de datos en memoria, ası́ como
añadir alguna información inicial, al inicio de la ejecución del programa. Para
ello introduciremos el código mostrado en el Listado 7.5 en el evento OnCreate
del módulo de datos. La primera tabla, que almacenará el rastro de la ruta que
estamos siguiendo, la creamos sirviéndonos del componente TFDTable a cuya
propiedad TableName asignamos el valor Rastro. También agregamos un
par de entradas en la tabla. Es importante no olvidar enlazarla con el compo-
nente TFDLocalSQL, de lo contrario no formarı́a parte de la base de datos en
memoria y las consultas no la encontrarı́an. La segunda tabla, que contiene una
lista de lugares, la creamos mediante sentencias SQL y, de la misma forma, le
añadimos varias filas. Por último creamos una vista, enviando la sentencia SQL
al TFDConnection mediante el método ExecSQL.
1 procedure [Link](Sender: TObject);
2 begin
3 with FDTable1 do
4 begin
5 [Link](’Lugar’, ftInteger);
6 [Link](’TimeStamp’, ftDateTime);
7 [Link](’Coords’, ftString, 18);
8 [Link](’Altitud’, ftFloat);
9 [Link](’Comentario’, ftString, 40);
10
11 CreateDataSet;
12
13 AppendRecord([1, Now,’(37.779594, -3.784906)’, 574, ’⤦
Ç Salida’]);
14 AppendRecord([1, IncMinute(Now, 120), ’(37.769031, ⤦
Ç -3.807063)’, 923, ’Castillo’]);
15
16 [Link](FDTable1);
17
18 Open;
19 end;
20
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
222 BASES DE DATOS EN MEMORIA
21 with FDConnection1 do
22 begin
23 ExecSQL(
24 ’CREATE TABLE Lugares (Codigo INT PRIMARY KEY, Nombre ⤦
Ç TEXT)’);
25 ExecSQL(
26 ’INSERT INTO Lugares VALUES (1, "Jaén")’);
27 ExecSQL(
28 ’INSERT INTO Lugares VALUES (2, "Los Villares")’);
29 ExecSQL(
30 ’INSERT INTO Lugares VALUES (3, "Torredelcampo")’);
31 end;
32
33 [Link](
34 ’CREATE VIEW LugaresRastro AS ’ +
35 ’ SELECT Nombre, Altitud, Comentario ’ +
36 ’ FROM Rastro R ’ +
37 ’ INNER JOIN Lugares L ’ +
38 ’ ON [Link]=[Link]’);
39 end;
Listado 7.5 Código que generará la base de datos en memoria
Una vez que se ejecute este código la base de datos estará disponible para la
aplicación. Podemos utilizarla como lo harı́amos con cualquier otra.
7.4.2 Diseño de la interfaz de usuario
El formulario de esta aplicación estará dividido en dos partes bien diferencia-
das. En la superior tendremos una cuadrı́cula que mostrará la tabla Rastro,
con la información que teóricamente se va añadiendo del sensor de posición.
También dispondremos un TBindNavigator para facilitar las operaciones de
edición sobre el contenido de la cuadrı́cula. La parte inferior del formulario
tendrá otra cuadrı́cula, ası́ como un TEdit y un TButton. El objetivo es faci-
litar la ejecución de cualquier consulta usando el TQuery que habı́amos añadido
al módulo de datos, mostrando el resultado obtenido en la cuadrı́cula.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CASO PRÁCTICO 223
La división en dos partes la efectuaremos introduciendo en el formulario dos
controles TPanel, uno ajustado a la parte superior y el otro ocupando el resto
del espacio disponible. Dentro de cada TPanel colocaremos el resto de los con-
troles citados, tal y como se aprecia en la Figura 7.4. En la ventana de estructura,
visible en el margen izquierdo, podemos apreciar la relación entre contenedores
y controles insertados en ellos.
Figura 7.4 ESTRUCTURA DE LA INTERFAZ DE USUARIO
El paso siguiente será vincular las cuadrı́culas, los dos controles TGrid, con
sus respectivos orı́genes de datos. El superior lo conectaremos con el TFDTable
y el inferior con el TFDQuery. Este trabajo podemos hacerlo agregando ma-
nualmente los TBindSourceDB y TBindingsList o bien usando el L IVE -
B INDINGS D ESIGNER (véase la Figura 7.5) para establecer las conexiones me-
diante operaciones de arrastrar y soltar.
El enlace entre el TGrid superior y el TBindNavigator con el
componente TFDTable facilitará tanto la visualización de los datos de la tabla
Rastro como su edición. El TGrid inferior, por el contrario, no mostrará
nada hasta en tanto no se ejecute alguna consulta sobre el TFDQuery. Para
ello haremos doble clic sobre el TButton y añadiremos el código mostrado a
continuación:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
224 BASES DE DATOS EN MEMORIA
Figura 7.5 E NLACE DE LAS CUADR ÍCULAS CON LOS COMPONENTES DE DATOS .
1 procedure TfrmMain.Button1Click(Sender: TObject);
2 begin
3 with dmMemoria.FDQuery1 do
4 begin
5 Close;
6 [Link];
7 [Link]([Link]);
8 Open;
9 end;
10 end;
Listado 7.6 Código asociado al botón de ejecución de consultas
Ahora ya estamos en disposición de ejecutar el programa y probar su fun-
cionamiento (véase la Figura 7.6), editando el contenido de la cuadrı́cula supe-
rior y ejecutando consultas en la inferior.
En las consultas podemos hacer referencia tanto a las dos tablas que componen la
base de datos en memoria como a la vista que las relaciona. Así, podríamos
obtener una lista de los lugares registrados con la consulta SELECT * FROM
Lugares, obtener una lista de todos los comentarios por orden cronológico con
la consulta SELECT Comentario FROM Rastro ORDER BY
TimeStamp, etc.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EXPORTACIÓN DE LOS DATOS 225
Figura 7.6 LA APLICACI ÓN MOSTRANDO LA BASE DE DATOS EN MEMORIA
NOTA
Aunque no hemos incluido un TBindNavigator asociado al TGrid
inferior, esto no nos impedirı́a modificar los datos que se están mostrando.
Es perfectamente posible, por ejemplo, seleccionar el contenido de la tabla
Lugares y modificar los códigos o nombres de los lugares.
7.5 Exportación de los datos
El uso de una base de datos en memoria implica que cada vez que se salga de la
aplicación la información se pierda, recreándose al volver a ejecutarse. Por ello
es una opción adecuada para casos en los que, por regla general, los datos no
serán necesarios nada más que durante la ejecución del programa.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
226 BASES DE DATOS EN MEMORIA
Puede darse el caso, no obstante, en que al usuario le interese exportar los
datos que ha obtenido para usarlos posteriormente, posiblemente desde otra apli-
cación. El supuesto registro efectuado por el ejercicio previo, por ejemplo,
podrı́a ser analizado después con otra aplicación para representar las coorde-
nadas en un mapa o medir distancias.
Componentes como TFDMemTable y TFDQuery disponen de un método
SaveToFile, con el que se crearı́a un archivo XML conteniendo la estructura
y los datos. Es la función a la que se invoca con la opción S AVE T O F ILE
que se explicó anteriormente, al describir la definición de la estructura en la
fase de diseño con un TFDMemTable. El inconveniente de este método es que
únicamente guardará el contenido de un conjunto de datos, la información del
TFDTable o TFDQuery en cuestión, pero no toda la base de datos.
7.5.1 El componente TFDSQLiteBackup
Dado que la base de datos en memoria se construye usando el controlador de
SQLite, resulta posible utilizar componentes especı́ficos de dicho controlador
para operar sobre ella. Uno de esos componentes es TFDSQLiteBackup,
cuya finalidad es realizar una copia de seguridad de una base de datos SQLite
cualquiera.
Para utilizar este componente hemos de establecer la configuración de copia,
llamando a continuación a su método Backup. La configuración se fija me-
diante las siguientes propiedades:
DriverLink: Debemos asignar a esta propiedad una referencia al
componente TFDPhysSQLiteDriverLink que esté utilizando la
base de datos. Es un parámetro que podemos establecer desde el
Inspector de objetos, abriendo la lista desplegable adjunta y seleccionando
el componente que representa el controlador SQLite.
DatabaseObj o Database: Origen de la copia de seguridad. La primera
propiedad indica que se trata de un objeto, una base de datos en memoria,
mientras que la segunda se usa cuando el origen es un archivo en disco.
DestDatabase o DestDatabaseObj: Destino de la copia de seguri-
dad. La primera propiedad se usa cuando el destino es un archivo en disco,
mientras que la segunda usarı́a como destino un objeto en memoria.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EXPORTACIÓN DE LOS DATOS 227
El componente TFDSQLiteBackup generará el evento OnProgress mien-
tras dure la operación de copia de datos desde el origen al destino, consultando
las propiedades PageCount y Remaining para determinar el porcentaje de
trabajo ya hecho.
7.5.2 En la práctica
Podemos agregar la posibilidad de exportar los datos usados por la anterior apli-
cación incluyendo en el módulo de datos un componente TFDSQLiteBackup,
enlazándolo con el componente TFDPhysSQLiteDriverLink e implemen-
tando un método como el mostrado a continuación:
1 with FDSQLiteBackup1 do
2 begin
3 DatabaseObj := [Link];
4 DestDatabase := ’[Link]’;
5 Backup;
6 end;
Listado 7.7 Exportación de la base de datos en memoria a un archivo
La propiedad CliObj de un TFDConnection devuelve el objeto interno
asociado al controlador que está utilizando. En este caso facilitarı́a el objeto
SQLite que gestiona la base de datos en memoria que, en definitiva, es lo que
queremos salvaguardar.
Desde el formulario que actúa como interfaz de usuario llamarı́amos a este
método, por ejemplo al cerrar la aplicación o bien a demanda, agregando un
nuevo botón a la interfaz. El archivo [Link] podrı́amos abrirlo
después desde otra aplicación, como cualquier base de datos. De hecho, bastarı́a
con definir una conexión desde el Explorador de datos de Delphi para poder abrir
el archivo y explorar su contenido, accediendo incluso a los datos que contiene
tal y como se muestra en la Figura 7.7.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
228 BASES DE DATOS EN MEMORIA
Figura 7.7 EXAMINAMOS LOS DATOS EXPORTADOS CON EL TFDSQLI T EBA C K U P
7.6 Resumen
Este capı́tulo nos ha servido para conocer una configuración adicional de tra-
bajo con bases de datos mediante FireDAC. Hemos utilizado fundamentalmente
componentes que ya conocı́amos, pero operando únicamente con información
alojada en memoria, sin una conexión real con una base de datos.
Además de para los supuestos mencionados anteriormente, esta configura-
ción también nos servirı́a al trabajar con aplicaciones distribuidas, en las que el
programa cliente obtiene datos de un servidor remoto, trabaja sobre ellos de
manera desconectada, con una base de datos en memoria, y transfiere los
cambios al final.
Una vez que hemos conocido las variantes más importantes de conexión a
datos en aplicaciones mono-capa, en las que los datos residen en la misma
máquina que ejecuta la aplicación, en el próximo capı́tulo, último de esta
primera parte del libro, trataremos un tema totalmente distinto pero de vital
importancia: el uso de Unicode con FireDAC.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Capı́tulo 8
BASES DE DATOS Y
UNICODE
Las aplicaciones que desarrollemos, especialmente aquellas que cuentan con una
interfaz web o están dirigidas a dispositivos móviles, es probable que sean uti-
lizadas por personas que utilizan diferentes idiomas. Incluso si la interfaz de
usuario únicamente está en un idioma concreto, por ejemplo en inglés, dichos
usuarios necesitarán almacenar datos usando su propio idioma, lo cual puede
plantearnos un cierto desafı́o si dicho idioma usa un alfabeto distinto al cono-
cido habitualmente como occidental.
¿Está nuestro programa preparado para permitir el tratamiento de datos con
caracteres de otros alfabetos? Si utilizamos una versión reciente de Delphi una
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
230 BASES DE DATOS Y UNICODE
buena parte del trabajo ya lo tendremos hecho, ya que desde su versión 2009 los
tipos de datos básicos para el almacenamiento de caracteres y cadenas de carac-
teres son Unicode. No obstante, es preciso determinar si la base de datos donde
alojamos la información, ası́ como los elementos de acceso a la misma, están
correctamente configurados para facilitar el almacenamiento y recuperación de
datos Unicode.
En este capı́tulo comenzaremos introduciendo brevemente qué es Unicode y
sus diferentes codificaciones, familiarizándonos con la forma en que se codifi-
can los caracteres y cadenas de caracteres en Delphi, para abordar después los
detalles relativos al trabajo con datos Unicode en distintas bases de datos.
8.1 Introducción a Unicode
Los ordenadores almacenan toda la información con la que trabajamos como
secuencias de números, incluyendo los textos. Esto hace necesario aplicar un
proceso de codificación y descodificación cada vez que un carácter es alma-
cenado o recuperado del almacenamiento. Dependiendo de qué asociación se
establezca entre las secuencias numéricas y las grafı́as dependerá de que el re-
sultado obtenido sea un texto que podamos leer o una nube ilegible de caracteres
inconexos.
8.1.1 Estándares de codificación: ASCII
La codificación de caracteres mediante códigos numéricos ya se usaba antes
de la llegada de los ordenadores. En estos se han utilizado distintas codifica-
ciones, dependiendo de los paı́ses e incluso los fabricantes, hasta que emergieron
estándares como EBCDIC (Extended Binary Coded Decimal Interchange Code)
y ASCII (American Standard Code for Information Interchange). Este último
fue el utilizado mayoritariamente en los ordenadores personales.
Originalmente el estándar ASCII usaba únicamente 7 bits, por lo que podı́an
representarse un máximo de 128 caracteres distintos. De estos una parte, los
primeros 32, estaban ocupados por códigos de control, mediante los que se indi-
caban acciones a los dispositivos tales como el avance de lı́nea, retorno de carro,
avance de página, etc. El resto eran suficientes para contener los números, letras
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
INTRODUCCIÓN A UNICODE 231
minúsculas y mayúsculas y algunos sı́mbolos, por supuesto siempre que nuestro
idioma fuese el inglés. Como puede apreciarse en la Figura 8.1, prácticamente
no habı́a espacio para más.
Figura 8.1 C ONJUNTO DE CARACTERES ASCII DE 7 BITS .
Dado que la práctica totalidad de ordenadores personales de los 70 e inicios
de los 80 procesaban los datos en bloques de 8 bits, existı́a la posibilidad de
extender el conjunto ASCII estándar agregando 128 caracteres adicionales. Ası́
nació el conjunto de caracteres ASCII extendido. La tabla de grafı́as mostrada en
la Figura 8.2 corresponde al conjunto extendido usado por el sistema operativo
DOS en paı́ses de lengua hispana. No solo se incluı́an caracteres acentuados y
la eñe, sino que habı́a espacio adicional para otros sı́mbolos y también algunos
caracteres gráficos.
En realidad la parte extendida de ASCII se configuraba según conviniese a
cada paı́s, usando para ello distintas páginas de codificación con las que se in-
cluı́an las grafı́as apropiadas. A pesar de ello seguı́an existiendo alfabetos que
no tenı́an cabida en este sistema de codificación por su limitada capacidad, exis-
tiendo otros, por ejemplo en Japón, que utilizaban 16 o 32 bits para poder repre-
sentar todos los sı́mbolos que necesitaban.
Durante el tiempo en que los sistemas informáticos operaron como islas, sin
conexiones hacia el exterior, el uso de diferentes sistemas de codificación no
suponı́a un mayor problema. El intercambio de datos a escala global, sobre todo
tras emerger la Web como plataforma de acceso a la información y aplicaciones,
provocó que se buscara una solución capaz de acoger todos los caracteres de los
distintos idiomas de nuestro planeta, ofreciendo una codificación unificada que
eliminase las barreras existentes a la hora de compartir los datos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
232 BASES DE DATOS Y UNICODE
Figura 8.2 CONJUNTO DE CARACTERES ASCII EXTENDIDO DE 8 BITS
8.1.2 Unicode y las codificaciones UTF-N
El estándar Unicode nació con el objetivo de definir una codificación común para
todos los caracteres y sı́mbolos utilizados en cualquier lengua, eliminando ası́
las barreras que suponı́an los distintos sistemas de codificación, incompatibles
entre sı́, utilizados históricamente por cada paı́s, sistema hardware o software.
Este ambicioso objetivo ha ido cumpliéndose paulatinamente, a lo largo de las
diferentes versiones del estándar en las que se incluyen nuevos code point, de-
nominación que reciben los códigos numéricos correspondientes a los caracteres
y otra información asociada a los mismos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
INTRODUCCIÓN A UNICODE 233
La última versión de Unicode es la 7.0 y se compone de 112 956 elemen-
tos distintos, incluyendo caracteres de múltiples alfabetos1 (véase la Figura 8.3),
ideogramas, sı́mbolos matemáticos, etc. Como es fácil deducir a partir de dicho
número, se precisan 32 bits (4 bytes) para cada code point2 . No obstante, los
alfabetos de uso más común tienen asignados códigos numéricos representables
con 16 bits o incluso con 8 bits. De hecho, el alfabeto estándar usado en inglés
sigue coincidiendo con la codificación que tenı́a en ASCII, por lo que bastan 8
bits para cada carácter. Utilizar 4 bytes por carácter en estos casos representarı́a
una ocupación innecesaria de memoria.
Figura 8.3 CONJUNTOS DE CARACTERES EXISTENTES EN UNICODE
1
Podemos consultar los distintos conjuntos de caracteres existentes en Unicode, agrupa-
dos por zonas geográficas y lenguas, en [Link]
2
La primera versión de Unicode utilizaba solo 16 bits, pero ante la imposibilidad de re-
presentar todos los alfabetos con esa capacidad se amplió a 21 bits en la versión 2.0.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
234 BASES DE DATOS Y UNICODE
NOTA
Unicode también asigna code points a elementos como los caracteres de
control de ASCII y otro tipo de elementos que no son caracteres en sı́, como
las composiciones de varios sı́mbolos, información de formato, etc.
Unicode estructura todos los elementos que es capaz de representar en sub-
conjuntos de 65 536 unidades a los que denomina planos. En total existen 17
planos, por lo que teóricamente podrı́an asignarse códigos a más de un millón
de caracteres y sı́mbolos, si bien hay rangos que están reservados para el uso por
parte de empresas y el propio consorcio que gestiona Unicode. Al primero de
esos planos se le conoce habitualmente como BMP (Basic Multilingual Plane),
siendo necesarios únicamente dos bytes para hacer referencia a cualquiera de sus
elementos.
Con el objeto de optimizar la ocupación en memoria y, sobre todo, el tamaño
de los documentos que almacenan información Unicode, existen tres formatos
de transformación distintos (UTF, Unicode Transformation Format), conocidos
como UTF-32, UTF-16 y UTF-8. Como es fácil deducir, el número final indica la
cantidad de bits usada para representar cada elemento, si bien en los dos últimos
casos esa cantidad es en realidad variable.
Cuando se utiliza UTF-32 toda la información sobre cada code point está
alojada en los 4 bytes, por lo que no es precisa ningún procesamiento adicional.
Una cadena de caracteres de este tipo ocuparı́a cuatro veces su longitud en bytes,
lo cual representa en la mayorı́a de los casos, salvo que estemos almacenando
información de idiomas asiáticos, un gasto innecesario de espacio en las bases
de datos.
Mediante UTF-16 cada elemento ocupa 2 bytes salvo que haya que represen-
tar caracteres no occidentales, en cuyo caso se utiliza una pareja de elementos
de 2 bytes (conocida como surrogate pair) para representarlo. En general, para
las lenguas europeas el uso de UTF-16 supone utilizar la mitad de espacio que
con UTF-32, sin ninguna limitación en cuanto a los caracteres y sı́mbolos que
es posible utilizar. La codificación y descodificación usando UTF-16 conlleva,
a diferencia de UTF-32, seguir un cierto algoritmo, relativamente sencillo, en
lugar de interpretar directamente el contenido.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
INTRODUCCIÓN A UNICODE 235
El formato de transformación de UTF-8, que es el más usado en la Web y
en general para el intercambio de datos, emplea un único byte para representar
los primeros 256 caracteres. Estos coinciden con el mapa ISO-8859-1 (también
conocido como Latin1) en el que aparecen la mayorı́a de caracteres europeos.
Para caracteres fuera de este conjunto se utilizarán 2, 3 o 4 bytes, dependiendo
del alfabeto al que pertenezcan. Por tanto UTF-8 ofrece la representación más
compacta, por una parte, y también compatibilidad con ASCII y la codificación
ISO-8859-1 que es probablemente la más utilizada. El mayor inconveniente de
UTF-8 es que precisa seguir un procedimiento de codificación y descodificación
algo más complejo que en los casos anteriores, por lo que su procesamiento
requiere algo más de tiempo.
8.1.3 Unicode y cabecera BOM
Dado que Unicode codifica cada carácter/sı́mbolo utilizando una secuencia de
bytes, el orden de este es importante. Históricamente los procesadores han uti-
lizado Big Endian o Little Endian dependiendo de su arquitectura (RISC o CISC)
y del fabricante. Al intercambiar documentos que usan UTF-32 o UTF-16 es
importante saber cuál es ese orden, ya que de lo contrario el receptor de la infor-
mación podrı́a obtener un documento indescifrable en lugar de uno legible. Con
UTF-8 no existe este problema por la forma en que está definido el formato de
transformación.
Los archivos codificados con UTF-32 cuentan con un primer elemento (4
bytes), denominado BOM (Byte Order Mark), con el que se indica si el orden
de los bytes es Big Endian (00 00 FE FF) o Little Endian (FF FE 00 00).
En el caso de UTF-16 el BOM ocupa 2 bytes y será FE FF o FF FE, respecti-
vamente.
A pesar de que UTF-8 no precisarı́a de un BOM al inicio del archivo, hay
editores que lo incluyen únicamente como firma UTF-8. El B LOC DE NOTAS
de Windows, por ejemplo, agrega automáticamente el BOM si se elige como
codificación Unicode o UTF-8 al guardar un archivo (véase la Figura 8.4). El
BOM en este caso ocupa 3 bytes: EF BB BF. La mayorı́a de los editores de
texto, incluyendo el de Delphi, interpretan adecuadamente el BOM y abren el
archivo como UTF-8, por lo que nunca veremos esa firma sino el contenido
correcto del archivo. No obstante, podemos utilizar un editor binario, como
el que aparece en la Figura 8.5, para examinar el contenido real del archivo,
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
236 BASES DE DATOS Y UNICODE
sin ningún tipo de tratamiento o interpretación. Ahı́ sı́ podremos verificar la
existencia del BOM.
Figura 8.4 OPCIONES DE CODIFICACI ÓN DEL BLOC DE NOTAS DE WINDOWS
Figura 8.5 COMPROBAMOS EL BOM A ÑADIDO POR EL BLOC DE NOTAS
8.2 Soporte Unicode en Delphi
Delphi ha contado con la capacidad de operar con cadenas de caracteres en las
que cada elemento se representa con 16 bits desde la versión 3, en la que se
introdujo el tipo WideString. Este facilitaba el trabajo con servicios de Win-
dows como OLE (Object Linking and Embedding) y el modelo de objetos COM
(Component Object Model) de Microsoft. Asociados al mismo existen los tipos
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOPORTE UNICODE EN DELPHI 237
de datos WideChar, para almacenar un carácter con 16 bits de almacenamiento,
y PWideChar, como puntero a una secuencia de caracteres WideChar. Ac-
tualmente el tipo WideString se mantiene en Delphi por compatibilidad hacia
atrás, pero raramente nos encontraremos en la necesidad de utilizarlo. El tipo de
cadena de uso preferente, y por defecto, es UnicodeString.
NOTA
Los compiladores Delphi para iOS y Android no soportan el tipo de dato
WideString, pero si el resto de tipos de cadenas de caracteres.
Los componentes de VCL y FMX están preparados para trabajar con Unicode,
ya que todas las propiedades y parámetros de métodos y eventos usan el citado
tipo UnicodeString. Esto incluye a los componentes de conexión a bases de
datos, ası́ como a los servicios de lectura y escritura de información en archivos
de la RTL.
Dado que el compilador y el entorno de Delphi están programados princi-
palmente en Delphi, el soporte de Unicode se extiende a todos los elementos y
podemos abrir y guardar archivos de texto Unicode, algo básico, pero también
utilizar cualquier carácter Unicode como parte de identificadores de variables
(véase la Figura 8.6), métodos, etc. Esto permite escribir el código usando los
sı́mbolos de nuestro propio idioma, no estando limitados a los usados en inglés
como ocurrı́a en el pasado.
Figura 8.6 UN IDENTIFICADOR DE VARIABLE EN JAPON ÉS
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
238 BASES DE DATOS Y UNICODE
8.2.1 Tipos de cadenas y caracteres
Desde la versión 2009 Delphi cuenta con un nuevo tipo de dato para trabajar
con cadenas de caracteres, UnicodeString, que se une a las que ya existı́an
de antes: AnsiString y WideString. La diferencia fundamental entre
UnicodeString y WideString es que su funcionamiento interno, a pe-
sar de almacenar el texto como UTF-16, se asemeja más al de AnsiString y
al de las cadenas en Pascal en general. Esto significa que tiene un contador de re-
ferencias interno y puede ser usado como siempre hemos hecho con el String
básico de Pascal.
El tipo String es en Delphi un sinónimo de UnicodeString. En conse-
cuencia, cualquier aplicación en la que utilizásemos el tipo String al compi-
larla con una versión reciente de Delphi pasará a trabajar automáticamente con
cadenas Unicode. El resto de los tipos se mantienen por compatibilidad. Si real-
mente necesitamos trabajar con cadenas de caracteres ASCII, no tenemos más
que usar el tipo AnsiString en lugar de String.
Análogamente, los tipos Char y PChar son ahora sinónimos de WideChar
y PWideChar. Si necesitamos trabajar con caracteres exclusivamente ASCII
debemos usar el tipo AnsiChar y, para cadenas ASCII terminadas con nulo, el
tipo PAnsiString.
Podemos apreciar la diferencia entre las cadenas UnicodeString (o
simplemente String) y las AnsiString con un sencillo ejercicio.
Introduce en un formulario Delphi tres TLabel y tres TEdit para introducir
una cadena Unicode y mostrar su longitud y ocupación y los mismos elementos,
por ejemplo a la derecha, para hacer lo mismo con cadenas ANSI. Para obtener la
longitud de una cadena en caracteres seguiremos usando el método Length. La
ocupación en bytes la calcularemos multiplicando esa longitud por el valor
devuelto por la función StringElementSize. Esta toma como parámetro
una cadena y devuelve la ocupación en bytes de cada uno de sus elementos.
El texto que se introduzca en los componentes TEdit siempre será Unicode,
ya que su propiedad Text es de tipo String. Para poder trabajar con cadenas
no Unicode necesitamos utilizar una variable de tipo AnsiString. Por ello
vamos a añadir en la parte privada de la clase la declaración de dos variables,
una de tipo AnsiString y otra de tipo String, que usaremos como almace-
namiento de los datos introducidos en los controles TEdit:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOPORTE UNICODE EN DELPHI 239
1 ...
2 private
3 { Private declarations }
4 cadAnsi: AnsiString;
5 cadUnicode: String;
6 ...
Listado 8.1 Declaración de variables
EJEMPLO 8.1 [Link]
Puedes encontrar este proyecto completo en la carpeta
TiposUnicode. No se precisa ninguna configuración adicional
para poder compilar y ejecutar.
Para actualizar la información mostrada en el formulario aprovecharemos los
eventos OnChange de los TEdit en los que se introducirá el texto, básicamente
trasladando el contenido de la propiedad Text a la variable correspondiente de
las antes declaradas. Por último se invocará a un método interno que se en-
cargará de actualizar los datos sobre longitud y ocupación. El código de estas
operaciones es el mostrado a continuación:
1 procedure [Link];
2 begin
3 [Link] := cadUnicode;
4 [Link] := cadAnsi;
5
6 [Link] := IntToStr(length(cadUnicode));
7 [Link] := IntToStr(StringElementSize(cadUnicode⤦
Ç ) * Length(cadUnicode));
8 [Link] := IntToStr(length(cadAnsi));
9 [Link] := IntToStr(Length(cadAnsi) * ⤦
Ç StringElementSize(cadAnsi));
10 end;
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
240 BASES DE DATOS Y UNICODE
11
12 procedure [Link](Sender: TObject);
13 begin
14 cadAnsi := [Link];
15 UpdateGUI;
16 end;
17
18 procedure [Link](Sender: TObject);
19 begin
20 cadUnicode := [Link];
21 UpdateGUI;
22 end;
Listado 8.2 Actualización de datos de longitud y ocupación de las cadenas
La reasignación del contenido de las variables a la propiedad Text de los
TEdit tiene por finalidad reflejar la información con la que realmente se está
trabajando. El segundo TEdit permitirı́a la introducción de caracteres Unicode,
pero al asignar su propiedad Text a la variable de tipo AnsiString parte de
la información se perderı́a, por ello volvemos a asignar la variable a la citada
propiedad. Es algo que podemos comprobar escribiendo algún carácter no occi-
dental en dicho control, comprobaremos cómo se pierde y en su lugar aparece el
carácter ?. En la Figura 8.7 puede verse el programa en funcionamiento.
Figura 8.7 DIFERENCIAS ENTRE UNA CADENA UNICODE Y UNA ANSI
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOPORTE UNICODE EN DELPHI 241
NOTA
La ocupación real de una de cadena de caracteres en Delphi es algo
superior a la que aparece en este ejercicio, ya que en él no se ha con-
siderado la cabecera que contiene datos como la longitud de la cadena,
el contador de referencias a la misma, el tamaño de cada elemento,
etc. Puedes encontrar información sobre la estructura de dicha cabecera
en [Link]
Unicode_in_RAD_Studio.
Al igual que hemos hecho siempre, podemos acceder a un carácter indivi-
dual de una cadena utilizando la sintaxis varCadena[ı́ndice]. Hemos de
tener en cuenta, no obstante, que cada elemento no ocupa un byte, por lo que el
ı́ndice no actúa como un desplazamiento en bytes desde el inicio de la cadena.
Cualquier código que tengamos en el que se asuma que cada elemento ocupa
un byte deberı́amos revisarlo y corregirlo ya que probablemente no genere el
resultado que deberı́a. Asimismo no podemos asumir que el valor devuelto por
Length es la ocupación de los caracteres de la cadena en bytes, por ejemplo
a fin de reservar memoria o indicar el número de bytes a transferir. Todas estas
son operaciones potencialmente peligrosas en las que dichas suposiciones han
de eliminarse.
La conclusión, llegados a este punto, es que Delphi está preparado para tra-
bajar con datos Unicode siempre que usemos los tipos por defecto, Char y
String, que son los mismos que se usan en propiedades y parámetros de los
componentes VCL/FMX. No hay ningún problema, por tanto, en crear una inter-
faz de usuario que acepte entradas en cualquier idioma y poder almacenar esos
datos internamente. Los obstáculos pueden surgir a la hora de almacenar esa
información o de recuperarla de un fuente externa, casos en los que podrı́a ser
necesario aplicar la conversión adecuada.
8.2.2 Conversión entre codificaciones
Las cadenas ANSI/ASCII pueden usar distintas páginas de códigos, utilizándose
por defecto aquella establecida por la configuración local del sistema. A pesar de
que el número de caracteres usados a la vez es limitado, seleccionando la página
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
242 BASES DE DATOS Y UNICODE
adecuada es posible representar prácticamente cualquier carácter o sı́mbolo. A
partir del tipo AnsiString podemos definir tipos de cadena ANSI que utilicen
páginas concretas sin más que especificar su código, por ejemplo:
1 type
2 // Página de códigos ISO-2022-JP para Japonés
3 JapString = type AnsiString(50220);
4
5 ...
6
7 procedure [Link](Sender: TObject);
8 var
9 ansiJap: JapString;
10 uniJap: String;
11 begin
12 uniJap := ’Caracteres en japonés’;
13 ansiJap := uniJap;
14
15 ShowMessage(’uniJap: ’ + uniJap + #13#10 + ’ansiJap: ’ + ⤦
Ç ansiJap);
16 end;
Listado 8.3 Titulo
Figura 8.8 USO DE CADENAS ANSI CON P ÁGINAS DE C ÓDIGOS ALTERNATIVAS
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOPORTE UNICODE EN DELPHI 243
Este programa se supone que tiene unos datos en japonés almacenados en una
variable String, de tipo Unicode, pero que precisa convertir a ANSI por alguna
razón. Como podemos apreciar, una simple asignación ha sido suficiente para
conseguir los mismos datos en un AnsiString con la configuración adecuada.
EJEMPLO 8.2 [Link]
Puedes encontrar este proyecto completo en la carpeta
Codificaciones. No se precisa ninguna configuración adi-
cional para poder compilar y ejecutar.
Puedes encontrar una lista de códigos de página en [Link]
assignments/character-sets/[Link]. El incon-
veniente de este tipo de representación, frente a Unicode, es que resulta indis-
pensable conocer el código de página en que se encuentra un cierto texto para
poder interpretarlo adecuadamente. No obstante, puede ocurrir que una apli-
cación tenga que tratar con datos no Unicode que corresponden a una página
concreta de códigos, siendo la anterior una solución para tratar con dicha infor-
mación adecuadamente.
La clase TEncoding
La RTL nos ofrece, en el módulo [Link], una clase cuya finalidad
es definir de manera explı́cita la codificación de un carácter o de una cadena:
la clase TEncoding. Esta es una alternativa generalmente más adecuada para
convertir datos entre distintas representaciones, ya sea en memoria, al recuperar-
los desde archivos o al almacenarlos.
Mediante el método GetEncoding de la clase TEncoding podemos crear
un objeto asociado a una codificación concreta, facilitando como parámetro el
código que tiene asociado. Existen objetos ya predefinidos asociados a las codi-
ficaciones más comunes. Podemos obtenerlos mediante propiedades de la clase
TEncoding como UTF8, Unicode o ANSI. La propiedad Default de-
vuelve un objeto TEncoding con codificación ANSI asociada a la página de
códigos actual en el caso de Windows.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
244 BASES DE DATOS Y UNICODE
Una vez que tenemos un objeto TEncoding, con la codificación que nos
interese, podemos utilizar sus métodos para recuperar la secuencia de bytes que
corresponde a una cadena o, a la inversa, obtener una cadena a partir de una se-
cuencia de bytes con la codificación adecuada. Esta es la finalidad de los métodos
GetBytes y GetString, respectivamente. Con el método GetByteCount
se determina la longitud de la secuencia de bytes generados a partir de una ca-
dena.
Las secuencias de bytes, que no son más que vectores del tipo Byte, pueden
ser escritas y leı́das de archivos, enviadas y recibidas por un canal de trans-
misión de datos y, operando sobre ellas en memoria, interpretarse de una forma
u otra según convenga. El método GetBytes toma como argumento una ca-
dena de caracteres en la codificación para la que se ha configurado el objeto
TEncoding, devolviendo como resultado un valor de tipo TBytes, cuya defi-
nición es TArray<Byte>. Análogamente, GetString toma como entrada
la secuencia de bytes y construye la cadena en la codificación adecuada, de-
volviéndola como un valor de tipo String.
Usando el método Convert de TEncoding es posible convertir entre dife-
rentes tipos de codificaciones. Precisa tres parámetros como entrada: un objeto
TEncoding indicando la codificación en que se encuentra actualmente la in-
formación, otro objeto del mismo tipo especificando la codificación de salida
y, por último, la secuencia de bytes de la cadena a convertir. El valor devuelto
como resultado será la secuencia de bytes en la nueva codificación. Asumiendo
que tenemos las variables ansiJap y uniJap del ejercicio previo, el ejemplo
siguiente, que forma parte del mismo proyecto, muestra cómo realizar la con-
versión de una codificación a otra mediante el citado método Convert.
1 var
2 AnsiJapones, Unicode: TEncoding;
3
4 begin
5 AnsiJapones := [Link](50220);
6 Unicode := [Link];
7
8 ansiJap := [Link]( [Link](
9 Unicode, AnsiJapones, [Link](uniJap)));
10
11 ShowMessage(ansiJap + ’ (ANSI) -> ’ +
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOPORTE UNICODE EN DELPHI 245
12 IntToStr([Link](ansiJap))
13 + ’ bytes’ + #13#10 +
14 uniJap + ’ (Unicode)-> ’ +
15 IntToStr([Link](uniJap)) +
16 ’ bytes’);
Listado 8.4 Conversión entre codificaciones
La última sentencia de este ejemplo utiliza el método GetByteCount para
mostrar la ocupación total del texto en cada codificación. Como puede apre-
ciarse en la Figura 8.9, contando todos los elementos que conforman la cadena
la representación en ANSI finalmente ocupa más que la cadena codificada como
UTF-16.
Figura 8.9 CONTENIDO REAL DE CADA VARIABLE
8.2.3 Lectura/Escritura de archivos Unicode
La clase TEncoding también nos resultará de utilidad a la hora de leer in-
formación de archivos y almacenarla. En el primer caso podemos detectar la
codificación del texto, en caso de que no la conociésemos y el archivo contuviese
BOM, mientras que en el segundo especificarı́amos la codificación de almace-
namiento. Con este fin recurrirı́amos a los siguientes métodos de TEncoding:
GetBufferEncoding: Tomando como primer argumento una secuen-
cia de bytes, correspondiente a una cadena, este método intenta detectar
la codificación y la longitud del preámbulo (la cabecera con el BOM). El
segundo parámetro será un objeto de tipo TEncoding y con valor nil o
una codificación a comprobar. Si el valor es nil el método devolverá en ese
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
246 BASES DE DATOS Y UNICODE
mismo parámetro la codificación detectada3 , en caso contrario solamente se
verificará si el contenido coincide con la codificación indicada. El valor de
retorno de la función facilita la longitud del preámbulo.
GetPreamble: Devuelve como resultado una secuencia de bytes con el
preámbulo correspondiente a la codificación asociada al objeto TEncoding.
La finalidad es facilitar su escritura al inicio de un archivo.
NOTA
Si conocemos la codificación de un archivo que vamos a leer o es-
cribir, podemos establecerla directamente al invocar a métodos como
LoadFromFile y SaveToFile. Estos aceptan como segundo argu-
mento un parámetro de tipo TEncoding.
Veamos en la práctica cómo leer un archivo de texto sin conocer la codifi-
cación, pero asumiendo que será UTF-16, UTF-8 o, en su defecto, ANSI con
la página de códigos del sistema; cómo cambiar dicha codificación y cómo
guardarlo nuevamente.
EJEMPLO 8.3 [Link]
Puedes encontrar este proyecto completo en la carpeta CodArchivo.
No se precisa ninguna configuración adicional para poder compilar y
ejecutar. Necesitaras al menos un archivo con codificación UTF-8 o
UTF-16 para realizar pruebas.
Comenzaremos diseñando una interfaz de usuario como la mostrada en la Figura
8.10. En la parte superior hemos dispuesto un TToolBar con dos TButton,
tres TRadioButton y un TCheckBox, usando los textos que se ven para la
3
Este método es en realidad muy básico y solamente verifica si los primeros tres o cuatro
bytes existentes en la secuencia coinciden con las firmas de UTF-8 o UTF-16. En el resto de
los casos no serı́a de utilidad.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOPORTE UNICODE EN DELPHI 247
propiedad Text de cada uno de ellos. El resto del espacio está ocupado por un
control TMemo que servirá para mostrar el texto. También se han incluido un
componente TOpenDialog y un TSaveDialog. Los usaremos para facilitar
la selección del archivo a abrir y el nombre del archivo al guardarlo, respectiva-
mente.
Figura 8.10 GUI DEL PROGRAMA PARA CARGAR/GUARDAR CON CODIFICACI ÓN
Completaremos la definición de la clase del formulario, derivada de TForm,
agregando los miembros necesarios para mantener en memoria el contenido del
archivo que se haya cargado, ası́ como la codificación q ue le corresponde y la
longitud del preámbulo si es que cuenta con él. También se incluirán dos métodos
adicionales que vamos a implementar de inmediato:
1 private
2 contenido: TBytes;
3 codActual: TEncoding;
4 longPreambulo: Integer;
5 function getEncoding: TEncoding;
6 procedure setEncoding(encoding: TEncoding);
Listado 8.5 Miembros a agregar a la clase derivada de TForm
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
248 BASES DE DATOS Y UNICODE
La finalidad del método getEncoding es devolver un objeto TEncoding
u otro dependiendo del TRadioButton que haya activo en la interfaz de usuario.
Complementariamente, el método setEncoding recibe un objeto TEncoding
como parámetro y activa el botón de radio correspondiente. La implementación
de esos dos métodos es la mostrada a continuación:
1 function [Link];
2 begin
3 if [Link] then
4 result := [Link]
5 else if [Link] then
6 result := TEncoding.UTF8
7 else result := [Link];
8 end;
9
10 procedure [Link](encoding: TEncoding);
11 begin
12 [Link] := encoding = [Link];
13 [Link] := encoding = TEncoding.UTF8;
14 [Link] := encoding = [Link];
15 end;
Listado 8.6 Métodos para obtener y establecer la codificación
Al hacer clic sobre el primero de los TButton el programa permitirá car-
gar cualquier archivo de texto, detectar su codificación y mostrar su contenido
en el TMemo. Tras ajustar el tamaño del vector contenido a partir de la in-
formación obtenida del archivo y cargar en ella todo su contenido, recurriremos
al método GetBufferEncoding para determinar la codificación actual. Si
el preámbulo tiene una longitud superior a 0 bytes esto indicará que existe un
BOM, por lo que activamos o desactivamos el TCheckBox en función de esta
condición. Finalmente mostramos el contenido y activamos el botón de radio
correspondiente para indicar la codificación:
1 procedure [Link](Sender: TObject);
2 var
3 archivo: TFileStream;
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOPORTE UNICODE EN DELPHI 249
4 begin
5 if [Link] then
6 begin
7 archivo := [Link]([Link], ⤦
Ç fmOpenRead);
8 SetLength(contenido, [Link]);
9 [Link](Pointer(contenido)ˆ, Length(contenido⤦
Ç ));
10 [Link];
11 codActual := nil;
12 longPreambulo := [Link](contenido, ⤦
Ç codActual);
13
14 [Link] := longPreambulo > 0;
15
16 [Link] := [Link](contenido);
17 setEncoding(codActual);
18 end;
19 end;
Listado 8.7 Carga de un archivo y detección de la codificación
El evento OnChange de los tres controles TRadioButton estará conec-
tado a un mismo evento. Su finalidad será convertir el texto de su codificación
original a la actualmente seleccionada y mostrarlo de nuevo en el TMemo. Para
ello usaremos el siguiente código:
1 procedure [Link](Sender: TObject);
2 var
3 codNueva: TEncoding;
4 begin
5 codNueva := getEncoding;
6
7 [Link] := [Link](
8 [Link](codActual, codNueva, contenido));
9 end;
Listado 8.8 Conversión entre codificaciones
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
250 BASES DE DATOS Y UNICODE
Esta conversión puede no tener efecto alguno en lo que estamos viendo en el
formulario si la conversión no implica pérdida de información. Es lo que ocurre
al convertir de ANSI a UTF-8 o de UTF-8 a UTF-16. La conversión de un
texto que originalmente usa alguna de estas dos últimas codificaciones a ANSI,
por el contrario, sı́ que puede causar una pérdida de información y que el texto
mostrado en el TMemo cambie. Volviendo a seleccionar la codificación original
recuperarı́amos el texto.
En realidad la finalidad principal de los TRadioButton y TCheckBox es
indicar la configuración del archivo leı́do originalmente, por una parte, y estable-
cer la que deseamos utilizar al guardar la información de nuevo en un archivo.
Esto ocurrirá al pulsar el segundo TButton, ejecutando el siguiente código:
1 procedure [Link](Sender: TObject);
2 var
3 archivo: TFileStream;
4 codNueva: TEncoding;
5 preambulo, contArchivo: TBytes;
6 despContenido: Integer;
7 begin
8 if [Link] then
9 begin
10 codNueva := getEncoding;
11 archivo := [Link]([Link], ⤦
Ç fmCreate);
12 if [Link] then
13 begin
14 preambulo := [Link];
15 [Link](preambulo[0], Length(preambulo));
16 end;
17 contArchivo := [Link](codActual, codNueva,
18 contenido, longPreambulo,
19 Length(contenido) - longPreambulo);
20 [Link](contArchivo[0], Length(contArchivo));
21 [Link];
22 end;
23 end;
Listado 8.9 Guardar el texto con la configuración establecida
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
SOPORTE UNICODE EN DELPHI 251
Tras crear el archivo, con el nombre que se haya indicado en el cuadro de
diálogo abierto por el TSaveDialog, se escribe en él el preámbulo en caso de
que el TCheckBox esté marcado. A continuación se convierte la información de
su codificación original a la actualmente seleccionada, escribiendo el resultado
en el archivo.
Para probar el programa (véase la Figura 8.11) lo mejor es partir de un archivo
en codificación UTF-8 o UTF-16 con BOM, de forma que al abrirlo se detecte
adecuadamente. A continuación podemos guardarlo en UTF-8 sin BOM o en
ANSI y usar un editor hexadecimal para examinar el preámbulo o su ausencia,
según los casos.
Figura 8.11 EL PROGRAMA EN FUNCIONAMIENTO MOSTRANDO LA CONFIGURACI ÓN
DE UN ARCHIVO RECI ÉN ABIERTO
Si el archivo que interesa cargar usa una página de códigos ANSI distinta de
la fijada por defecto por el sistema el texto no aparecerá legible en este programa,
ya que no es capaz de determinar esa información por sı́ solo.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
252 BASES DE DATOS Y UNICODE
NOTA
En caso de que utilicemos los métodos LoadFromFile y
SaveToFile de un objeto TStrings, por ejemplo el asociado a
la propiedad Lines del TMemo, además de poder indicar la codificación
a usar también es posible establecer mediante la propiedad WriteBOM, de
tipo Boolean, si ha de escribirse o no el BOM en los archivos.
8.3 Bases de datos y Unicode
A diferencia de lo que ocurre cuando se opera con información procedente de
archivos de distintos orı́genes, cada uno de los cuales podrı́a emplear una codi-
ficación distinta, al trabajar con una base de datos toda la información utilizará
la misma codificación. Si es necesario efectuar conversiones, por ejemplo en-
tre la codificación empleada por el RDBMS y la usada por un programa que
actúa como interfaz de usuario de acceso a la misma, estas serán llevadas a cabo
automáticamente por el controlador o los componentes FireDAC, según los ca-
sos. Para ello, no obstante, hemos de establecer la configuración adecuada en
cada uno de los elementos que participan en una solución de este tipo. Esa será
nuestra responsabilidad.
8.3.1 Configuración Unicode en FireDAC
Los componentes FireDAC de las actuales versiones de Delphi, entendiendo
aquellas posteriores a 2009, están preparadas para realizar automáticamente la
conversión entre codificaciones de caracteres cuando sea preciso. Internamente
las consultas y parámetros a enviar al gestor de bases de datos, en propieda-
des como SQL (componente TFDQuery) y CommandText (TFDCommand),
se almacenan siempre como Unicode. Esto nos permite, por ejemplo, intro-
ducir en una consulta texto en idiomas que usan otros alfabetos distintos al nues-
tro. Dependiendo de la configuración del controlador cliente de cada DBMS,
FireDAC se encargará de realizar la conversión a la codificación que corres-
ponda. Análogamente los conjuntos de datos resultantes, por ejemplo los obtenidos
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
BASES DE DATOS Y UNICODE 253
de una consulta, pasarán por el mismo proceso cuando sea aplicable. Lo único
que hemos de tener en cuenta, por tanto, es que la configuración del controlador
cliente que estemos utilizando sea la adecuada (véase siguiente apartado).
Dado que los controles utilizados para solicitar y mostrar información, con los
que diseñamos nuestras interfaces de usuario, almacenan internamente los datos
con codificación Unicode, uno de los pocos casos en los que necesitaremos reali-
zar conversiones explı́citas será cuando la información proceda de una fuente ex-
terna. Supongamos que vamos a importar o exportar datos de un archivo de texto
a una base de datos, por ejemplo utilizando el componente TFDDataMove.
Implı́citamente se establecerá la codificación del conjunto de datos (clase derivada
de DataSet) que actuará como origen o destinatario, pero la codificación del
archivo de texto es necesario establecerla explı́citamente mediante la propiedad
TextFileEncoding del citado componente. Otro tanto ocurrirı́a al utilizar
el componente TFDBatchMoveTextReader para leer un archivo de texto o
el componente TFDBatchMoveTextWriter para escribir en él.
Veamos la implementación práctica del caso que acaba de mencionarse. Con-
cretamente tendremos unos datos en un archivo CSV externo con codificación
UTF-8, datos que supuestamente queremos importar a una base de datos aunque,
en este ejercicio, vamos a limitarnos a mostrarlos una vez que se encuentren en
un TFDQuery, sin llegar a transferirlos realmente a un RDBMS. El contenido
del archivo CSV con el que vamos a trabajar es el mostrado parcialmente en la
Figura 8.12.
EJEMPLO 8.4 [Link]
Puedes encontrar este proyecto completo en la carpeta UnicodeBDD.
No se precisa ninguna configuración adicional para poder compilar y
ejecutar, salvo disponer el archivo [Link] en la carpeta ade-
cuada.
El objetivo es importar el contenido del archivo CSV, usando la codificación
adecuada, a un TFDQuery que, a su vez, conectaremos a una cuadrı́cula de
datos a fin de mostrar la información. A continuación se detalla el proceso a
seguir.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
254 BASES DE DATOS Y UNICODE
Figura 8.12 VISTA PARCIAL DEL CONTENIDO DEL ARCHIVO CSV
Partiendo de un proyecto vacı́o vamos a agregar un módulo de datos, como en
los demás ejercicios, en el que incluiremos la siguiente lista de componentes:
TFDConnection: Este componente servirá como punto de unión para
los dos siguientes, facilitando el uso del motor de bases de datos de SQLite.
Únicamente modificaremos la propiedad LoginPrompt, a la que asignare-
mos el valor False.
TFDLocalSQL: Nos permitirá trabajar directamente con la base de datos
en memoria, efectuando la consulta de recuperación de datos. Al agregarlo
deberı́a conectarse automáticamente con el anterior, algo que podemos ve-
rificar en el valor de la propiedad Connection.
TFDQuery: Será el componente que ejecute la consulta y obtenga como
resultado el conjunto de datos. Asignaremos a su propiedad SQL la consulta
SELECT * FROM japeng.
TFDMemTable: Este componente será el destinatario de la operación de
transferencia de datos desde el archivo CSV, generando el DataSet que se
transferirá al TFDQuery llegado el momento.
TFDBatchMoveTextReader: Será el componente encargado de leer los
datos almacenados en el archivo CSV, para lo cual es necesario establecer
la configuración adecuada modificando las siguientes propiedades:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
BASES DE DATOS Y UNICODE 255
– Encoding: Seleccionaremos de la lista desplegable la opción ecUTF8,
indicando ası́ la codificación en que se encuentran los datos.
– FileName: Haremos clic en el botón asociado para abrir el cuadro de
diálogo que nos permitirá elegir el archivo que deseamos abrir.
– DataDef: Mediante esta propiedad estableceremos el separador de
campos y otros parámetros que afectan a la lectura de los datos. Asig-
nando a la propiedad RecordFormat el valor rfCommaDoubleQuote
obtenemos la configuración básica que necesitamos. Además usaremos
la propiedad Fields para definir el nombre y tipo de los datos campos
existentes en el archivo CSV, tal y como se muestra en la Figura 8.13.
Figura 8.13 DEFINICI ÓN DE LOS CAMPOS DEL ARCHIVO CSV
TFDBatchMoveDataSetWriter: La finalidad de este componente será
transferir los datos leı́dos por el anterior a un derivado de TDataSet. Para
ello desplegaremos la lista asociada a su propiedad DataSet y elegiremos
el TFDMemTable introducido anteriormente.
TFDBatchMove: Es el último componente a agregar al módulo de datos.
Se encargará de conectar a los dos anteriores mediante las propiedades
Reader y Writer. La propiedad Analyze ha de quedar vacı́a, con todas
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
256 BASES DE DATOS Y UNICODE
las opciones desmarcadas, ya que el TFDBatchMoveTextReader tiene
la información necesaria para interpretar el contenido del archivo CSV.
Al ejecutar la aplicación se invocará al método Open del TFDQuery, lo cual
provocará que este demande del TFDLocalSQL la ejecución de la consulta que
asignamos a su propiedad SQL. Lo que hará este último componente será gene-
rar el evento OnGetDataSet, en el que introduciremos el código mostrado a
continuación. El método Execute del TFDBatchMove se encargará de ejecu-
tar la transferencia de datos del archivo CSV al TFDMemTable, resultado que
finalmente será devuelto como contenido del TFDQuery:
1 procedure TdmUnicode.FDLocalSQL1GetDataSet(ASender: TObject;⤦
Ç const ASchemaName,
2 AName: string; var ADataSet: TDataSet; var AOwned: Boolean⤦
Ç );
3 begin
4 try
5 [Link];
6 [Link];
7 ADataSet := FDMemTable1;
8 AOwned := True;
9 except on E: Exception do
10 ShowMessage([Link]);
11 end;
12 end;
Listado 8.10 Transferencia de los datos CSV al TFDQuery
En cuanto a la interfaz de usuario de la aplicación, únicamente agregaremos al
formulario un control TGrid. Enlazaremos este con el componente TFDQuery
del módulo de datos usando, como es habitual, el diseñador de L IVE B INDINGS.
Por lo demás, únicamente usaremos el evento OnShow del formulario para invo-
car al método Open del TFDQuery, desencadenando ası́ la sucesión de eventos
que provocará la lectura del archivo CSV, su transferencia a la base de datos
en memoria y, finalmente, la visualización en la cuadrı́cula. El resultado será
similar al mostrado en la Figura 8.14 siempre y cuando la configuración de la
codificación del archivo y el componente TFDBatchMoveTextReader sea
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
BASES DE DATOS Y UNICODE 257
la adecuada. Si cambiásemos la propiedad Encoding de este último el texto
obtenido probablemente serı́a ilegible.
Figura 8.14 L A APLICACI ÓN MOSTRANDO LOS DATOS LE ÍDOS DEL ARCHIVO CSV.
NOTA
Aunque en este ejercicio el archivo es CSV y se han obtenido un conjunto
de filas y columnas de datos, la configuración al leer de un archivo externo
también se aplicarı́a al recuperar el contenido de un archivo de texto, por
ejemplo para almacenarlo en un campo de la base de datos. En este caso se
introducirı́a en el campo únicamente el texto ya convertido (si fuese nece-
sario), pero no tiene sentido incluir el BOM ya que ni los RDBMS ni la
aplicación lo necesitan.
8.3.2 Aspectos especı́ficos de los RDBMS
Una vez que tenemos la información en nuestra aplicación, ya sea obtenida de
una fuente externa como en el ejercicio previo o bien tras la introducción directa
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
258 BASES DE DATOS Y UNICODE
por parte del usuario, llega el momento de almacenarla en la base de datos. Para
evitar cualquier pérdida de información es necesario que el controlador cliente
esté adecuadamente configurado, para lo cual podemos usar el cuadro de diálogo
C ONNECTION E DITOR asociado al componente TFDConnection (véase la
Figura 8.15).
La configuración por defecto para determinados RDBMS ya asume el uso de
UTF-8 como codificación para el texto, por lo que no se precisa ningún ajuste
adicional. Si elegimos SQL Server como controlador de la conexión, por
ejemplo, se asumirá que la codificación es Unicode. Al trabajar con Interbase,
Firebird u Oracle, por el contrario, es nuestra responsabilidad configurar la
codificación.
Figura 8.15 C ONFIGURACI ÓN DE LA CODIFICACI ÓN PARA UNA CONEXI ÓN A
INTERBASE
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
RESUMEN 259
Si creamos la base de datos utilizando una herramienta externa a Delphi,
habremos de utilizar las opciones especı́ficas de la misma para configurar la
codi-ficación de caracteres. Posteriormente, al conectar con ella mediante
FireDAC, será cuando fijemos la configuración del software cliente mediante el
anterior cuadro de diálogo.
8.4 Resumen
Jorge Villalobos
, en este capı́tulo hemos conocido los aspectos
fundamentales de la codificación de caracteres con Unicode, frente a estándares
heredados como ASCII, y la forma en que funcionan UTF-8, UTF-16 y
UTF-32, incluyendo el uso de la cabecera BOM allı́ donde es necesario. Como
se ha mostrado, el soporte de Unicode en Delphi es completo, incluyendo los
componentes relacionados con acceso a bases de datos.
Se ha explicado cómo realizar conversiones entre codificaciones, cómo
leer datos de archivos externos en distintas codificaciones y cómo
trasladarlos a componentes FireDAC. A partir de ese punto, siempre y
cuando el controlador de bases y el RDBMS estén apropiadamente
configurados, no tendremos ningún problema en almacenar y recuperar
información textual usando Unicode.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
PARTE 2
ACCESO A DATOS
EN APLICACIONES
CLIENTE/SERVIDOR
En esta segunda parte del libro vamos a abordar los temas relacionados con
el desarrollo de aplicaciones cliente/servidor, la arquitectura más conocida y uti-
lizada para soluciones dirigidas a empresas e instituciones en las que existe un
servidor de datos y un conjunto más o menos grande de clientes conectados
al mismo, habitualmente mediante una infraestructura propia de comunicación
como puede ser una red local.
En principio nos ocuparemos de los aspectos y procedimientos generales, los
propios de FireDAC, en este tipo de configuración, para después abordar temas
como la gestión de transacciones, estrategias de bloqueo o el trabajo sin conexión
a la base de datos y uso de cached updates, para terminar tratando algunos de-
talles especı́ficos del RDBMS InterBase.
Delphi permite conectar con un gran número de servidores distintos. El uso
de algunos de ellos requerirá formación especı́fica por parte de la persona que
vaya a administrarlos. Aquı́ nos ceñiremos sobre todo a las tareas propias del
desarrollador de aplicaciones, no a las del administrador de bases de datos.
Introducción al desarrollo cliente/servidor 263
Transacciones, bloqueos y notificación de cambios 311
Trabajar sin conexión al RDBMS 333
Interbase 359
Capı́tulo 9
INTRODUCCIÓN AL
DESARROLLO
CLIENTE/SERVIDOR
En los ejercicios desarrollados en la primera parte de este libro hemos utilizado
gestores de bases de datos locales, como SQLite, Microsoft Acccess e IBLite,
que operan directamente sobre la información en el mismo equipo que ejecuta
la aplicación. La comunicación entre los componentes FireDAC y el gestor de
datos es directa y, además, exclusiva, por lo que no suele darse ningún tipo de
conflicto de acceso a los datos ni de actualización de los mismos.
La Figura 1.6 (véase página 54, en el primer capı́tulo) mostraba cómo al
acceder a RDBMS como InterBase, SQL Server u Oracle la comunicación entre
la aplicación y el servidor de datos se efectúa habitualmente mediante TCP/IP,
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
264 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
ya sea con una comunicación sin intermediarios o a través de controladores
heredados de tipo ODBC o dbExpress. El RDBMS permitirá múltiples cone-
xiones procedentes desde distintos orı́genes, existiendo un acceso concurrente a
los datos. No debe asumirse, por tanto, que se tiene un acceso exclusivo a los
mismos, sino que este es compartido con otros usuarios y aplicaciones.
En este capı́tulo vamos a conocer algunos conceptos fundamentales sobre
FireDAC a la hora de desarrollar aplicaciones cliente/servidor. Todos ellos son
genéricos y, por tanto, se aplican con independencia de cuál sea el RDBMS con-
creto con el que vayamos a trabajar.
9.1 Conexión con el servidor de datos
Ya sabemos que el primer paso para operar con una base de datos, con inde-
pendencia de que sea local o remota, consiste en establecer una conexión con la
misma. Para ello recurriremos al componente TFDConnection, encargado de
comunicarse con el software cliente del RDBMS en cuestión aportando la infor-
mación necesaria: el nombre de la base de datos, la ruta en que se encuentra, las
credenciales de acceso, etc.
Veamos cuáles son las diferencias en este campo entre lo que ya conocemos
y la conexión con una base de datos en configuración cliente/servidor.
9.1.1 Ruta y nombre de la base de datos
Para conectar con una base de datos local, como las utilizadas en capı́tulos pre-
vios, se precisa el nombre del archivo y la ruta en que se encuentra almacenado
en el sistema de archivos local. La composición de dicha ruta varı́a según el
sistema operativo en que se ejecute la aplicación, tal y como se mostró en su
momento. En general se asume que el archivo será abierto en exclusiva por una
aplicación, pudiendo esta realizar cualquier tipo de operación sobre los datos sin
mayores limitaciones.
La conexión con un RDBMS en una configuración cliente/servidor también
demanda conocer el nombre de la base de datos, pero la ruta será sustituida por el
nombre (o la dirección IP) de la máquina en la que está ejecutándose el servidor
de datos. Habitualmente el RDBMS estará atendiendo de forma simultánea a un
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONEXIÓN CON EL SERVIDOR DE DATOS 265
cierto número de clientes, por lo que, dependiendo de la capacidad de la lı́nea de
comunicación y el hardware del servidor, la conexión podrı́a no ser inmediata,
sino tardar un cierto tiempo o incluso fallar por completo en caso de que la
comunicación se interrumpa. Estos son aspectos que, por regla general, no es
necesario considerar en una configuración local.
NOTA
Aunque es habitual que los servidores de datos y aplicaciones en una
red propia tengan asignada una dirección IP estática, en lugar de obtenerla
mediante DHCP (Dynamic Host Configuration Protocol), es recomendable
no embeberla en el código de la aplicación sino mantenerla en un archivo
de configuración externo, de forma que pueda modificarse fácilmente.
Cada servidor de datos utiliza un puerto por defecto para aceptar las solici-
tudes de conexión entrantes por parte de los clientes. Estos, por tanto, han de
enviar sus peticiones a dicho puerto. Cada controlador usará por defecto di-
cho puerto, pero si este se hubiese cambiado en la configuración del servidor
también habrá que aplicar dicha modificación en la configuración del cliente.
Esto implica normalmente un cambio en el componente TFDConnection o el
archivo de configuración asociado. Lógicamente el citado puerto ha de encon-
trarse abierto para recibir conexiones entrantes en el servidor y salientes en los
clientes. Un fallo habitual al comenzar a trabajar con esta configuración es no
caer en la cuenta de que el software cortafuegos está bloqueando dichas cone-
xiones, lo cual hace imposible la comunicación y, por tanto, la conexión con el
RDBMS.
9.1.2 Autenticación de acceso
Una aplicación que almacena y recupera la información en el mismo sistema
en que se ejecuta, usando una base de datos local, normalmente no requerirá
credenciales adicionales. Se asume que si el usuario tiene acceso al sistema y
puede ejecutar la aplicación, esta puede operar sobre los datos. El escenario en
una configuración cliente/servidor es totalmente distinto. El servidor de datos
normalmente dará servicio a múltiples aplicaciones, alojando información a la
que no debe garantizarse un acceso universal para todos los usuarios.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
266 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
Dependiendo del RDBMS que se utilice, y la forma en que esté configurado,
nos podemos encontrar fundamentalmente con dos modalidades distintas de au-
tenticación:
OS: También conocida como autenticación de tipo trusted. Consiste en uti-
lizar las credenciales con las que el usuario ha iniciado sesión en el sistema
operativo para acceder al servidor de datos.
DBM: Habitualmente denominada autenticación nativa, se basa en la con-
figuración de los usuarios y sus contraseñas en la propia base de datos, de
forma que es necesario aportar dichas credenciales a la hora de acceder al
servidor.
Ciertos RDBMS, por ejemplo la versión 2.1 de Firebird, contemplan el uso de
una tercera configuración de autenticación conocida como mixed. Si al conectar
con el RDBMS se facilita un usuario y contraseña se recurre a la autenticación
nativa, utilizándose la del sistema operativo en caso contrario.
NOTA
Habitualmente la autenticación de tipo SO está asociada al uso de Win-
dows como sistema operativo. En una red Windows los usuarios al ini-
ciar sesión se identifican con unas credenciales que controla un servidor, un
equipo con Windows Server, que determina qué operaciones y privilegios
tiene cada usuario. Serı́an esas mismas credenciales las que se entregarı́an
al RDBMS, por ejemplo SQL Server, para que este hiciese lo propio sobre
los datos.
El componente TFDConnection cuenta con tres propiedades que determi-
nan qué método de autenticación se usará y las credenciales a aportar en caso
necesario. Son la siguientes:
OSAuthent: Esta propiedad booleana determina si se utilizará la autenti-
cación de tipo OS, asignándole el valor True, o la del propio RDBMS, con
el valor False. Este último es el valor que se asume por defecto.
UserName y Password: En caso de que la anterior propiedad sea False
y la conexión al servidor de datos requiera autenticación, estos dos campos
aportarán las credenciales necesarias.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONEXIÓN CON EL SERVIDOR DE DATOS 267
En el Editor de conexión del componente TFDConnection encontraremos
la propiedad OSAuthent (véase la Figura 9.1) únicamente para ciertos contro-
ladores de bases de datos, como InterBase, Firebird y Microsoft SQL Server.
Habitualmente la autenticación con credenciales del SO solo suele utilizarse con
SQL Server.
Figura 9.1 CONFIGURACI ÓN DEL M ÉTODO DE AUTENTICACI ÓN
9.1.3 Reutilización de conexiones
El proceso de conexión con una base de datos remota, según se apuntaba an-
teriormente, es un proceso costoso en tiempo y recursos, al implicar el inter-
cambio de una sucesión de paquetes de información a través de una red de co-
municaciones. En caso de que una aplicación vaya a abrir varias conexiones
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
268 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
simultáneas con la misma base de datos, por ejemplo en múltiples hilos de eje-
cución (threads) en paralelo, ese coste se multiplica. Para evitar este efecto,
FireDAC incorpora un mecanismo de reutilización de conexiones que es nece-
sario activar explı́citamente, ya que por defecto no lo está.
La reutilización de conexiones consiste en mantener un grupo o pool de cone-
xiones ya preparadas y abiertas, de forma que cuando la aplicación requiere una
conexión, por ejemplo para ejecutar una consulta, se toma una de las disponibles
en el grupo que no esté actualmente en uso. Cuando la ejecución de la con-
sulta finaliza, la conexión se devuelve al pool estando de nuevo disponible. De
esta forma no se abren y cierran conexiones con el RDBMS de forma reiterada,
reduciendo el tiempo necesario para realizar cada tarea. Al mismo tiempo, al
mantener un grupo limitado de conexiones abiertas con el servidor, también se
reduce la carga en este respecto a un escenario en el que cada hilo mantuviese
abierta una conexión independiente.
Para activar la reutilización de conexiones configuraremos el componente
TFDConnection atendiendo a las dos directrices siguientes:
1. Configuración compartida: Para poder reutilizar una conexión es
necesario que los parámetros de configuración de los distintos casos de
uso sean los mismos. En la conexión básicamente se aportará el nombre
de la base de datos sobre la que se operará y las credenciales necesarias
para operar sobre la misma, nada más.
2. Pooled: Entre los parámetros de configuración encontraremos esta pro-
piedad booleana, a la que hemos de dar el valor True para activar la reuti-
lización de la conexión.
NOTA
La reutilización o pooling solo puede utilizarse en conexiones persis-
tentes, alojadas en un archivo propio de conexiones del proyecto, o bien en
conexiones privadas a la aplicación, configuradas en tiempo de ejecución.
El funcionamiento del pool de conexiones compartidas puede configurarse
utilizando los siguientes parámetros de la propiedad Params del componente
TFDConnection:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONEXIÓN CON EL SERVIDOR DE DATOS 269
PoolMaximumItems: Esta propiedad establece el número máximo de
conexiones que se almacenarán en el pool. Por defecto toma el valor 50
que, en general, será más que suficiente para la mayorı́a de los proyectos.
El número de conexiones disponibles en el pool irá descendiendo a medida
que la aplicación vaya demandándolas para trabajar sobre la base de datos,
volviendo a incrementarse a medida que dichas tareas finalicen y las cone-
xiones se devuelvan. Si en algún momento el pool está vacı́o y la aplicación
solicita una nueva conexión se producirá una excepción.
PoolExpireTimeout: Establece el tiempo en milisegundos tras el cual
una conexión inactiva puede ser cerrada y eliminada del pool. Por defecto
su valor es 90 000, lo que implica que aquellas conexiones que lleven más
de 90 segundos sin ser utilizadas se cerrarán y eliminarán.
PoolCleanupTimeout: Tiempo en milisegundos que ha de transcurrir,
adicional al establecido por la propiedad anterior, antes de que FireDAC
elimine las conexiones no utilizadas. La configuración por defecto es de 30
segundos.
Un TFDConnection configurado como acaba de describirse tomará una
conexión del pool cada vez que se invoque al método Open o se asigne el
valor True a la propiedad Connected, por ejemplo al abrir una tabla o eje-
cutar una consulta. Al cerrar dicha conexión, volviendo a dar el valor False
a Connected, la conexión en realidad no se cerrará, sino que se devuelve al
pool a fin de poder reutilizarla. Si transcurrido el tiempo establecido por las pro-
piedades anteriores el programa no ha precisado una conexión disponible en el
pool, esta se cierra y se destruye. De esta forma, el número real de conexiones
existentes en el pool irá adaptándose a las necesidades de la aplicación en cada
momento, si bien nunca podrá superar el número establecido por la propiedad
PoolMaximumItems.
NOTA
Para aplicaciones con conexión esporádica al RDBMS, capaces de ope-
rar offline la mayor parte del tiempo, véase el Capı́tulo 11.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
270 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
9.1.4 Gestión de las conexiones durante la
ejecución
Al ejecutar una aplicación que utiliza FireDAC para acceder a bases de datos se
crea una instancia de la clase TFDCustomManager, a la que podemos acceder
mediante la función FDManager, encargada de leer las definiciones de
conexiones existente en el archivo de configuración, agregar nuevas conexiones,
mantener los datos de las conexiones abiertas, gestionar el pool de conexiones
reutilizables descrito en el apartado anterior, etc. Las propiedades y métodos
ofrecidos por dicha clase pueden sernos de utilidad en distintos escenarios. Aquı́
únicamente se mencionan algunos de ellos.
Mediante la propiedad Connections es posible acceder a la lista de cone-
xiones actualmente abiertas. La propiedad ConnectionCount indica cuántos
elementos hay en dicha lista. Cada elemento es un objeto TFDCustomConnec-
tion con los datos de la conexión y métodos que permiten actuar sobre la
misma.
La información relativa a definiciones de conexiones persistentes puede recu-
perarse mediante los métodos GetConnectionDefNames, que devuelve una
lista con los nombres de cada conexión, y GetConnectionDefParams, en-
cargado de facilitar la lista de parámetros de una conexión concreta. Asimismo
pueden agregarse nuevas definiciones de conexiones, mediante el método Add-
ConnectionDef, ası́ como eliminar cualquiera de las existentes, con el método
DeleteConnectionDef.
Las conexiones activas para una cierta definición de conexión pueden cerrarse
usando el método CloseConnectionDef. Este precisa como parámetro el
nombre asignado a la conexión (o el facilitado como primer parámetro al método
AddConnectionDef). Este método puede utilizarse, por ejemplo, para cerrar
todas las conexiones existente en el pool de conexiones reutilizables asociadas a
una definición concreta, sin esperar a los tiempos de expiración establecidos.
Veamos en la práctica cómo usar dos de los métodos citados para obtener
información de las conexiones FireDAC definidas en el s istema. Para ello cons-
truiremos una aplicación muy simple, con una interfaz de usuario conteniendo
dos controles TListBox. El primero estará alineado al margen izquierdo del
formulario y mostrará los nombres de las conexiones existentes. El segundo
ocupará el registro del formulario y, al seleccionar una conexión del anterior,
informará sobre los parámetros de configuración.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONEXIÓN CON EL SERVIDOR DE DATOS 271
Como es habitual, comenzaremos iniciando un nuevo proyecto de tipo multi-
dispositivo. A continuación incluiremos los dos controles TListBox, modifi-
cando su propiedad Align. La primera tomará el valor Left y la segunda el
valor Client. Acto seguido hacemos doble clic sobre el formulario, para abrir
el método asociado al evento OnCreate que será el que usemos para llenar la
primera lista. Para ello usaremos el método GetConnectionDefNames del
objeto devuelto por FDManager, tal y como se aprecia en el listado siguiente.
Al seleccionar un elemento de esta lista se generará el evento OnChange, señal
que aprovecharemos para recuperar la lista de parámetros de la conexión indi-
cada y mostrarla en la segunda lista.
EJEMPLO 9.1 [Link]
Puedes encontrar este proyecto completo en la carpeta
CSConnection. No se precisa ninguna configuración adicional
para poder compilar y ejecutar.
1 procedure [Link](Sender: TObject);
2 begin
3 [Link]([Link]);
4 end;
5
6 procedure TfrmMain.ListBox1Change(Sender: TObject);
7 begin
8 [Link]([Link], ⤦
Ç [Link]);
9 end;
Listado 9.1 Introducción de datos en las listas
La Figura 9.2 muestra el programa en funcionamiento, con una de las cone-
xiones predefinidas seleccionada y sus parámetros de conexión a la derecha.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
272 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
Figura 9.2 LISTA DE CONEXIONES Y PAR ÁMETROS
9.2 Obtención de datos
Una vez que se haya establecido la conexión con el servidor de datos, la recu-
peración de información se lleva a cabo utilizando los mismos componentes y
técnicas descritos en los capı́tulos previos. Existen, no obstante, algunas direc-
trices que es recomendable seguir. La más inmediata es que, salvo excepciones,
nunca deberı́a utilizarse el componente TFDTable, ya que raramente nos in-
teresará transferir desde el servidor hasta los clientes todas las filas y columnas
de una tabla. Por ello en aplicaciones cliente/servidor el método preferente para
obtener datos del RDBMS es el componente TFDQuery o, en su defecto, el
componente TFDStoredProc.
En una configuración cliente/servidor el cliente, la aplicación que actúa como
interfaz de usuario, ha de solicitar al servidor los datos que deben mostrarse al
usuario en cada momento. El número de filas y c olumnas a t ransferir desde
el servidor a través de la red tendrá un importante impacto en la experiencia del
usuario con nuestro programa, pudiendo introducir demoras que deterioren dicha
experiencia.
Los apartados de esta sección del capı́tulo sugieren el uso de algunas técnicas
básicas dirigidas a limitar la cantidad de datos a transferir entre cliente y servidor,
reduciendo el tiempo de respuesta de la aplicación y el uso de recursos como
el ancho de banda, la memoria en el cliente o la entrada/salida a disco en el
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
OBTENCIÓN DE DATOS 273
servidor. Conjuntamente, estas técnicas mejorarán la escalabilidad de la solución
y también la experiencia del usuario con la misma.
9.2.1 Selección de columnas
Por regla general las tablas de una base de datos contienen muchos más atributos
que los que es necesario mostrar en la interfaz de usuario de la aplicación. Por
esta razón, las consultas del tipo SELECT * FROM deberı́an evitarse, especifi-
cando en su lugar las columnas concretas que es necesario recuperar. Esta es una
acción que tiene un efecto multiplicativo, ya que cada columna eliminada de la
consulta afecta a todas las filas resultantes de la misma. El resultado es que el
RDBMS ha de recuperar menos información del disco y, sobre todo, se reduce
el volumen de datos a transportar por la red.
Figura 9.3 SELECCI ÓN DE CAMPOS CONCRETOS EN UNA CONSULTA
Si trabajamos habitualmente con el DATA E XPLORER ya sabemos que al
seleccionar una tabla del mismo y arrastrarla al módulo de datos lo que se obtiene
es un componente TFDTable, configurado para recuperar todo el contenido de
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
274 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
la tabla. En la práctica, cada uno de estos componentes deberı́a ser sustituido
por un TFDQuery, utilizando el Editor de consultas asociado para seleccionar
exactamente los campos que se precisan. La lista de campos de cada tabla es
algo que podemos consultar en el propio DATA E XPLORER, como se aprecia
en la Figura 9.3. Esta herramienta, el Editor de consultas, también nos permite
ejecutar la consulta y comprobar el resultado obtenido.
Habitualmente, además de las columnas de datos propiamente dichas también
será necesario seleccionar aquellas que identifiquen de manera única cada una de
las filas. En la Figura 9.3, por ejemplo, solamente se quiere mostrar el nombre de
cada una de las categorı́as de productos existentes, pero también se ha incluido
en la consulta la columnas con el identificador de dichas categorı́as. Este dato
será necesario para, por ejemplo, referenciar una cierta categorı́a desde otra tabla
o actualizar el nombre de una categorı́a.
NOTA
La base de datos que aparece abierta en el DATA EXPLORER en la
Figura 9.3 es AdventureWorks. Se trata de una base de datos de
ejemplo ofrecida por Microsoft para SQL Server. Puedes descargarla
desde la web de Microsoft, desempaquetarla y definir una conexión
FireDAC para acceder a la misma. Será la base de datos que utilicemos
en varios de los ejemplos de esta parte del libro.
9.2.2 Filtrado de filas
El mismo razonamiento aplicable a las columnas de una tabla es extrapolable
también a sus filas. Normalmente nunca ejecutaremos una consulta sobre la
base de datos sin incluir una cláusula WHERE a fin de recuperar exclusivamente
aquellas filas que necesite la aplicación, en lugar de transportar toda la tabla
completa desde el servidor al cliente.
Esto es especialmente importante en tablas con mucha información. No es el
caso de la tabla ProductCategory usada a modo de ejemplo en el apartado
anterior, ya que cuenta con únicamente cuatro filas. Tomemos en su lugar la tabla
SalesOrderDetail de la misma base de datos. Contiene más de 120 000 fi-
las de datos correspondientes a lı́neas de pedido, por lo que una consulta tı́pica
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
OBTENCIÓN DE DATOS 275
del tipo SELECT * FROM [Link] tardarı́a un tiempo
importante en ejecutarse al tener que transferir dicho volumen de datos por la
red. Además, el programa que actúa como cliente deberá contar con memoria
necesaria para almacenar toda esa información.
En el caso concreto que se expone el filtrado serı́a muy obvio: la aplicación
solamente requerirá las lı́neas correspondientes a un pedido concreto. La se-
lección de columnas y filtrado de filas permiten recuperar exactamente los datos
que se precisan, como se muestra en la Figura 9.4. En este caso el filtro de filas
utiliza un parámetro sustituible, de forma que la consulta se podrı́a utilizar de
forma genérica para cualquier pedido.
Figura 9.4 CONSULTA CON FILTRADO DE FILAS Y SELECCI ÓN DE COLUMNAS
9.2.3 Paginación de resultados
Con independencia del filtrado que llevemos a cabo en la propia consulta, la
configuración por defecto del componente TFDQuery limita el n úmero de filas
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
276 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
que son transmitidas desde el servidor al cliente. Esta configuración por defecto,
ajustada para ir paginando los resultados a medida que se precise, puede modi-
ficarse cambiando los valores de los campos de la propiedad FetchOptions
del citado componente.
Las subpropiedades esenciales de FetchOptions en relación a la página
de resultados son las siguientes:
RowsetSize: Establece el número de filas que serán transferidas en cada
operación de recuperación o, desde otra perspectiva, fija el tamaño de cada
conjunto de filas o recordset. El valor por defecto es 50. un TFDQuery
mantendrá normalmente en memoria dos conjuntos de filas de dicho tamaño,
actuando como una ventana deslizable sobre el total de filas resultantes de la
consulta. La recuperación de paquetes adicionales dependerá de la siguiente
propiedad.
Mode: Esta propiedad indica al componente cómo se gestionará la recu-
peración de paquetes de filas desde el servidor. Los valores que puede tomar
son:
– fmOnDemand: Es el valor por defecto. Los conjuntos de filas son
solicitados al servidor a medida que lo demande la navegación por los
datos. FireDAC utilizará en el servidor el recurso más apropiado para
facilitar este tipo de funcionamiento, según el RDBMS utilizado.
– fmAll: Con esta configuración el componente recuperará todas las filas
resultantes de la consulta en cuando se abra la conexión, almacenándolas
localmente. Este es un proceso que puede tardar un cierto tiempo, de-
pendiendo de la cantidad de datos a transferir, pero una vez completado
permite navegar por la información sin necesidad de solicitudes
ulteriores.
– fmManual: Al asignar este valor a Mode la responsabilidad de solicitar
los paquetes de datos al servidor recae en el programador, que deberá
agregar el código necesario para efectuar dicha tarea.
De optarse por el modo de recuperación de datos manual, asignando el valor
fmManual a [Link], al abrir el TFDQuery no se recuperarán
filas de forma automática. Tendremos que utilizar los métodos FetchAll y
FetchNext para solicitar todas las filas resultantes de la consulta o el siguiente
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
OBTENCIÓN DE DATOS 277
paquete, respectivamente. El número máximo de filas de cada paquete vendrá
determinado por el valor de la propiedad RowsetSize descrita anteriormente.
Las filas a incluir en cada paquete de datos, con independencia de que su
recuperación sea manual o automática, también se verá afectada por el valor
de las propiedades RecsSkip y RecsMax de la propiedad FetchOptions.
Por defecto la primera tiene el valor 0 y la segunda el valor -1, por lo que se
recuperará desde la primera fila un paquete de datos del tamaño indicado por
RowsetSize. Asignando a RecsSkip un valor distinto de cero conseguire-
mos saltar el número de filas indicadas antes de comenzar a recuperar. Con
RecsMax limitaremos el número de filas a obtener, indicando el valor -1 la
ausencia de lı́mite.
NOTA
Si tras asignar el valor fmManual a [Link] abrimos
el Editor de consultas del TFDQuery para ajustar la consulta o comprobar
su funcionamiento, hemos de tener en cuenta que al ejecutar la consulta no
se obtendrá ningún dato. Tendrı́amos que cambiar temporalmente el valor
a fmOnDemand para que esta herramienta del entorno funcione como es
habitual.
Veamos en la práctica cómo servirnos de dos de las propiedades citadas,
RecsSkip y RecsMax, para producir un efecto de paginación manual en la
interfaz de usuario. Para ello, partiendo de un nuevo proyecto al que agregamos
un módulo de datos, reproduciremos los pasos descritos a continuación:
1. Agregamos al módulo de datos un TFDConnection configurado para
acceder a la base de datos AdventureWorks de SQL Server. Si no con-
tamos con esta podemos utilizar cualquier otra, incluso trabajando con un
RDBMS distinto, en cuyo caso habrı́a que cambiar la consulta y referencias a
datos en los pasos siguientes.
2. Introducimos un componente TFDQuery en el módulo de datos, conectándolo
con la conexión anterior. A continuación abrimos el Editor de consultas aso-
ciado y escribimos la sentencia SQL mostrada en el Listado 9.2.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
278 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
1 SELECT SalesOrderId, OrderDate, CustomerID, TotalDue
2 FROM [Link]
Listado 9.2 Consulta de recuperación de pedidos
3. Cambiamos al formulario que actuará como interfaz de usuario e insertamos
en él los componentes mostrados en la Figura 9.5. El control TGrid está
vinculado con el TFDQuery, de forma que mostrará los datos recuperados
por este. El TEdit inferior tiene a True su propiedad ReadOnly, por lo
que no podrá ser modificado en ejecución.
Figura 9.5 ELEMENTOS A INTRODUCIR EN EL FORMULARIO
4. Abrimos el módulo de código asociado al formulario, agregando a la sección
privada de la definición de la clase la declaración de una variable entera y
un procedimiento. La variable, llamada UltimaFila, nos servirá para
establecer el número de filas a saltar en cada operación de lectura.
1 private
2 UltimaFila: Integer;
3 procedure Fetch;
Listado 9.3 Miembros a añadir a la definición de clase del formulario
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
OBTENCIÓN DE DATOS 279
5. A continuación escribimos la implementación del procedimiento Fetch,
cuya finalidad será provocar una solicitud de datos al servidor con los pará-
metros adecuados. Dado que el modo de recuperación de datos (propiedad
[Link]) del TFDQuery no se ha modificado, bastará con
desconectar y volver a conectar con la base de datos para provocar una so-
licitud de recuperación de filas. Las filas concretas a obtener vendrán de-
terminadas por el valor de las propiedades RecsSkip, que establecemos
a partir de la variable UltimaFila, y RecsMax, valor que recuperamos
del primer TEdit existente en la interfaz. La actualización del contenido
del TGrid será automática, tras lo cual procedemos a controlar el estado
de los botones dependiendo de que nos encontremos en la primera fila o en
la última.
1 procedure [Link];
2 begin
3 with [Link] do
4 begin
5 if UltimaFila < 0 then
6 UltimaFila := 0;
7
8 Disconnect;
9 [Link] := UltimaFila;
10 [Link] := StrToInt([Link]);
11 Open;
12
13 [Link] := UltimaFila <> 0;
14 [Link] := RecordCount >= StrToInt(edNumFilas⤦
Ç .Text);
15 [Link] := IntToStr(UltimaFila);
16 end;
17 end;
Listado 9.4 Implementación del procedimiento Fetch
6. Al anterior método se realizarán llamadas desde tres puntos diferentes: el
método asociado al evento OnShow del formulario y los métodos vincu-
lados al evento OnClick de los botones. En los tres casos primero se
actualiza el contenido de la variable UltimaFila, primero, y se invoca
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
280 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
al método Fetch, a continuación. El código correspondiente a esos tres
métodos es el siguiente:
1 procedure [Link](Sender: TObject);
2 begin
3 UltimaFila := 0;
4 Fetch;
5 end;
6
7 procedure TfrmMain.Button1Click(Sender: TObject);
8 begin
9 UltimaFila := UltimaFila - StrToInt([Link]);
10 Fetch;
11 end;
12
13 procedure TfrmMain.Button2Click(Sender: TObject);
14 begin
15 UltimaFila := UltimaFila + StrToInt([Link]);
16 Fetch;
17 end;
Listado 9.5 Código asociado a los botones
EJEMPLO 9.2 [Link]
Puedes encontrar este proyecto completo en la carpeta CSPaginate.
Deberás ajustar el componente TFDConnection para conectar con el
servidor SQL Server y abrir la base de datos AdventureWorks.
Al ejecutar el programa la cuadrı́cula deberı́a mostrar tantas filas como valor por
defecto se haya asignado al primer TEdit. Una vez en funcionamiento podemos
cambiar dicho valor, ası́ como utilizar los botones para ir navegar por los datos.
En la Figura 9.6 se muestra el programa en ejecución.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EDICIÓN DE DATOS 281
Figura 9.6 EL PROGRAMA EN FUNCIONAMIENTO MOSTRANDO UNA P ÁGINA DE DATOS
9.3 Edición de datos
En las secciones previas de este capı́tulo nos hemos ocupado de la conexión de
una aplicación cliente con el servidor de datos y de la recuperación de in-
formación, transfiriendo filas de datos desde el RDBMS a la interfaz del pro-
yecto. Habitualmente dicha interfaz también permitirá al usuario manipular di-
chos datos, ya sea añadiendo nuevas filas, cambiando valores de las existentes
o eliminándolas.
La finalidad de esta sección del presente capı́tulo es abordar diversos temas
relacionados con la edición de datos en un entorno cliente/servidor, siempre
centrados en el trabajo con componentes FireDAC. Algunos de estos temas,
como las actualizaciones por lotes, serán extendidos posteriormente, en los
siguientes capı́tulos.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
282 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
9.3.1 Cómo actualiza FireDAC los datos
Los proyectos que hemos desarrollado como ejemplo hasta ahora, especialmente
en la primera parte del libro, se caracterizan por facilitar la actualización in-
mediata de los datos que están mostrándose. No hay más que actuar sobre los
controles dispuestos en la interfaz de usuario, el TGrid o las opciones de nave-
gación ofrecidas por el componente TBindNavigator, para agregar nuevas fi-
las, cambiar el contenido de las existentes o eliminarlas. Estas operaciones sobre
el conjunto de datos, representado por el componente TFDTable, TFDQuery
o similar, se comunican de manera inmediata a la base de datos subyacente, con
independencia de la naturaleza de esta.
El procedimiento que sigue FireDAC para determinar si una cierta operación
es posible y, en caso afirmativo, enviarla al gestor de datos, consta de los pasos
siguientes:
1. Se determina si el conjunto de datos es de solo lectura o no, consultando
para ello la subpropiedad ReadOnly de la propiedad UpdateOptions.
En caso negativo se comprueba si contempla la operación a llevar a cabo
leyendo las propiedades booleanas EnableInsert, EnableUpdate y
EnableDelete. Las tres son también miembros de la mencionada pro-
piedad UpdateOptions (véase la Figura 9.7). Mediante estas cuatro pro-
piedades podemos configurar un TFDQuery para que no permita ninguna
operación de actualización, dando el valor False a ReadOnly, o bien de-
sactivando acciones concretas como la inserción, actualización o borrado.
Por defecto ReadOnly tendrá el valor False y las otras tres propiedades
estarán a True.
2. Para operaciones de inserción y actualización es necesario activar en el con-
junto de datos el modo apropiado antes de comenzar a asignar valores a los
campos. Con este fin se recurre a los métodos Append y Edit, respectiva-
mente. Tras haber dado a los campos el contenido deseado, una llamada al
método Post se encarga de enviar al gestor de datos la sentencia SQL ade-
cuada para completar la operación. Antes se llevarán a cabo comproba-
ciones, dependiendo del valor de las propiedades CheckRequired,
CheckUpdatable, etc., de la propiedad UpdateOptions.
3. Para operaciones de borrado se invoca directamente al método Delete del
conjunto de datos. Este se encargará de realizar las comprobaciones nece-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EDICIÓN DE DATOS 283
Figura 9.7 OPCIONES DE ACTUALIZACI ÓN DE UN CONJUNTO DE DATOS
sarias, por ejemplo aplicando cambios que hubiese pendientes de confirmar,
antes de proceder al borrado de la fila actual del conjunto de datos. Es una
operación que provoca el avance a la fila siguiente, ya que la que era actual
deja de existir.
En realidad los cambios producidos por los métodos Post y Delete serán
enviados de inmediato al gestor de datos solo si la propiedad CachedUpdates
del TFDQuery está a False. Ese es su valor por defecto y, dado que hasta el
momento no lo hemos modificado en ninguno de nuestros proyectos, las opera-
ciones de actualización de datos tienen un efecto inmediato.
NOTA
Véase la Sección 11.2 del Capı́tulo 11 para saber más sobre la propiedad
CachedUpdates y el uso de las actualizaciones de datos por lotes.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
284 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
9.3.2 Generación de las sentencias para ac-
tualizar datos
Las operaciones de inserción, modificación y borrado de datos son las tres que
conllevan una actualización del contenido de la base de datos, debiendo tra-
ducirse en las correspondientes sentencias SQL de tipo INSERT, UPDATE y
DELETE, respectivamente. Estas son generadas automáticamente por FireDAC,
siempre que se cumplan unas ciertas premisas, y enviadas al RDBMS para su
ejecución.
Lo primero que ha tenerse en cuenta es que solamente pueden generarse sen-
tencias de actualización a partir de un TFDQuery que contiene una consulta,
es decir, una sentencia SELECT de SQL. Dicha consulta deberá incluir entre
los campos obtenidos aquellos que formen la clave primaria correspondiente a
la tabla referenciada en la cláusula WHERE. FireDAC es capaz de identificar las
columnas de dicha clave y utilizarla adecuadamente para limitar las filas afec-
tadas. De no incluirse la clave primaria aún se intentará componer la sentencia
de actualización, pero esta podrı́a tener efectos indeseados si no se controla ade-
cuadamente.
Actualización y clave primaria
A la hora de determinar las filas de una tabla que se verı́an afectadas por una
operación de actualización podemos recurrir a tres enfoques diferentes. El que
se utilice en cada momento dependerá del valor que se asigne a la propiedad
[Link]. Los valores posibles son:
upWhereKeyOnly: Este es el valor asignado por defecto. Establece que
en la cláusula WHERE solamente aparecerán las columnas que formen la
clave primaria.
upWhereChanged: Seleccionando este modo se incluirán en la cláusula
WHERE tanto las columnas de la clave primaria como aquellos cuyo con-
tenido se haya modificado. De esta forma la aplicación se asegura de no
cambiar o eliminar una fila que haya sido alterada por otro usuario desde
que la recuperamos del servidor.
upWhereAll: Asignando este valor a UpdateMode conseguiremos que
en la cláusula WHERE se incluyan todas las columnas de la tabla, compa-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EDICIÓN DE DATOS 285
rando los valores que tenemos en la aplicación con los almacenados actual-
mente en la base de datos.
Comprobar el efecto de la propiedad UpdateMode sobre las sentencias de
actualización es relativamente sencillo. No tenemos más que recurrir a la utilidad
de monitorización de FireDAC para examinar las sentencias enviadas al servi-
dor en cada caso. Para ello necesitaremos un programa básico que nos permita
conectar con el RDBMS y modificar algún dato.
EJEMPLO 9.3 [Link]
Puedes encontrar este proyecto completo en la carpeta CSUpdate. De-
berás ajustar el componente TFDConnection para conectar con el
servidor SQL Server y abrir la base de datos AdventureWorks.
Figura 9.8 AJUSTAMOS LA CONSULTA A EJECUTAR
Partiendo de un proyecto vacı́o de tipo multi-dispositivo, al que añadimos un
módulo de datos, tomamos la tabla ProductCategory desde el Explorador
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
286 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
de datos y la arrastramos hasta el módulo, configurando ası́ la conexión y el
TFDQuery asociado. A continuación editamos la consulta de dicho componente
para seleccionar únicamente las columnas ProductCategoryId, que es la
clave primaria, y Name, que contiene el nombre de la categorı́a (véase la Figura
9.8). En principio no modificaremos la propiedad UpdateMode. También agre-
garemos al módulo de datos un componente TFDMoniRemoteClientLink
y, como es habitual, el TFDGUIxWaitCursor.
NOTA
No olvides dar el valor True a la propiedad Tracing del
TFDMoniRemoteClientLink y modificar el campo MonitorBy de
la propiedad Params del TFDConnection, asignándole el valor
mbRemote.
En el formulario del proyecto introduciremos únicamente un componente
TGrid, vinculándolo con el TFDQuery. Este control nos permitirá no sólo
navegar por los datos, sino también introducir cambios en los campos mostra-
dos. En este caso podrı́amos cambiar el nombre de las categorı́as.
Figura 9.9 SE LOCALIZA LA FILA A ACTUALIZAR USANDO LA CLAVE PRIMARIA
Con la opción T OOLS —F IRE DAC M ONITOR abrimos el monitor de co-
municación. A continuación ejecutamos el programa y modificamos el nombre
de una de las categorı́as. En la traza de eventos apreciaremos, como se mues-
tra en la Figura 9.9, que la sentencia UPDATE de actualización ha filtrado las
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EDICIÓN DE DATOS 287
filas a modificar usando exclusivamente la clave primaria. En este contexto
OLD ProductCategoryID representa el valor para dicha columna que fue
obtenido al recuperar los datos desde el servidor.
Si modificamos la propiedad UpdateMode del TFDQuery, asignándole el
valor upWhereChanged, y repetimos la operación anterior comprobaremos
cómo la sentencia de actualización ahora no solo utiliza la clave primaria para
encontrar la fila afectada, sino que también verifica que los campos que se han
cambiado, en este caso Name, tengan en la base de datos el valor que obtuvimos
inicialmente (véase la Figura 9.10).
Figura 9.10 LA CL ÁUSULA WHERE USA LA CLAVE PRIMARIA Y LOS CAMPOS
MODIFICADOS
Anteriormente se apuntaba que, en caso de que la consulta introducida en el
TFDQuery no incluyese entre sus columnas la clave primaria, la sentencia de
actualización podrı́a ser inadecuada. Es algo fácilmente comprobable: modi-
fica l a c onsulta d el p rograma a nterior p ara s eleccionar únicamente l a columna
Name. A continuación vuelve a ejecutar el programa e introduce algún cambio,
examinando la sentencia de actualización generada.
Como se aprecia en la Figura 9.11, la cláusula WHERE está usando como filtro
únicamente la columna modificada. Si hubiese varias filas con el mismo valor
en dicha columna, algo perfectamente posible, la actualización afectarı́a a todas
ellas. De ahı́ la importancia de incluir siempre la clave primaria en la consulta,
aunque no la necesitemos en la interfaz de usuario.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
288 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
Figura 9.11 LA SENTENCIA DE ACTUALIZACI ÓN PODR ÍA AFECTAR A M ÚLTIPLES FILAS
NOTA
Si el campo CountUpdateRecords de la propiedad
UpdateOptions del TFDQuery tiene el valor True, que es su
valor por defecto, tras cada actualización se comprobará que el número
de filas afectadas es exactamente 1, generándose una excepción en caso
de no ser ası́ y deshaciéndose la transacción de actualización previa. Por
tanto, en la práctica no serı́a posible actualizar por accidente más filas
de las deseadas, habrı́a que dar el valor False a la citada propiedad
CountUpdateRecords para permitirlo.
Especificar la tabla a actualizar
En ocasiones la consulta efectuada no incluirá el nombre de la tabla que real-
mente hay que actualizar. Esto ocurre, por ejemplo, cuando se utiliza una vista
como origen de la consulta o al componer consultas con campos agregados y
relaciones, de forma que el resultado obtenido, en caso de que se modifique al-
guna fila del mismo, no puede volver a la entidad referenciada en la cláusula
FROM de la sentencia SELECT.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EDICIÓN DE DATOS 289
Casos como los descritos en muchas ocasiones lo único que precisan conocer
es la tabla sobre la que ha de aplicarse la actualización, al incluirse en la consulta
todas las columnas necesarias para ello. El nombre de la tabla se facilitarı́a en
este caso en el campo UpdateTableName de la propiedad UpdateOptions.
Durante la fase de diseño no tenemos más que abrir la lista asociada a dicho
campo y elegir la tabla de destino de la actualización.
Supongamos que tenemos un TFDQuery con una consulta como la mostrada
a continuación, con la que queremos obtener el identificador y nombre de cada
categorı́a y de las subcategorı́as que le corresponden, obteniendo los datos visi-
bles en la Figura 9.12:
1 SELECT [Link], [Link],
2 [Link], [Link]
3 FROM [Link] As SubCategory
4 INNER JOIN [Link] As Category
5 ON [Link] = Category.⤦
Ç ProductCategoryID
Listado 9.6 Consulta no actualizable directamente
Figura 9.12 CONSULTA CON RELACI ÓN ENTRE DOS TABLAS
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
290 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
Si conectamos este componente a un TGrid e intentamos modificar el
nombre de una de las categorías1, al invocar al método Post (lo cual ocurre au-
tomáticamente al cambiar de fila en la cuadrícula) se generará una excepción.
La sentencia de actualización generada hace referencia a la tabla de subcatego-
rías, ya que esta es la que aparece en la cláusula FROM de la consulta.
Para que la tabla a actualizar sea la correcta tendremos que seleccionar el
TFDQuery, abrir la propiedad UpdateOptions en el Inspector de objetos,
desplegar la lista asociada a la subpropiedad UpdateTableName y elegir la
tabla [Link]. A pesar de este ajuste, al intentar
de nuevo modificar el nombre de una categorı́a nos encontraremos otra vez con
una excepción. Usando la herramienta de monitorización, a fin d e examinar
la sentencia de actualización empleada (véase la Figura 9.13), descubriremos
dónde está el problema: se está utilizando como clave en la actualización la
clave primaria de la tabla de subcategorı́as, en lugar de la correspondiente a la
tabla de categorı́as.
Figura 9.13 LA CLAVE PRIMARIA EMPLEADA NO ES LA CORRECTA
1
Asumamos que el nombre de las subcategorı́as es de solamente lectura y no puede ser
cambiado. Para que sea efectivamente ası́ no tenemos más que abrir el Editor de campos
asociado al TFDQuery, usar la opción A DD A LL F IELDS para añadir todos los campos de
la consulta, seleccionar las columnas de la tabla de subcategorı́as y asignar el valor True a su
propiedad ReadOnly.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EDICIÓN DE DATOS 291
Como se indicó con anterioridad, normalmente el componente TFDQuery es
capaz de detectar automáticamente los campos que forman la clave primaria.
Esto, no obstante, no es posible cuando se utilizan vistas o, como en este caso,
una consulta con relaciones entre tablas. En estos casos recurriremos al campo
KeyFields de la propiedad UpdateOptions para indicar explı́citamente
qué columnas forman la clave primaria. KeyFields tiene asociado un editor
especı́fico como el mostrado en la Figura 9 .14. En la lista de la izquierda apare-
cen todas las columnas resultantes de la consulta, de los cuales agregaremos a la
lista de la derecha aquellos que forman la clave primaria.
Figura 9.14 ESTABLECEMOS LA CLAVE PARA ACTUALIZAR
Tras realizar este último ajuste podemos volver a ejecutar la aplicación e in-
tentar modificar el nombre de cualquier categorı́a. En esta ocasión la operación
se ejecutará sin problemas, ya que la sentencia de actualización (véase la Figura
9.15) es totalmente correcta.
Personalización de las sentencias de actualización
A pesar de todas las posibilidades de ajuste que nos ofrecen las propiedades
citadas en los apartados previos, en ocasiones la sentencia de actualización para
un cierto conjunto de datos no podrá ser generada de forma automática. En estos
casos hemos de facilitar una sentencia de actualización personalizada, escrita
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
292 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
Figura 9.15 LA ACTUALIZACI ÓN SE COMPLETA SIN PROBLEMAS
manualmente y ajustada a las necesidades concretas de cada caso. En realidad,
en la mayorı́a de los casos tendremos que aportar tres sentencias SQL: una de
actualización, otra de inserción y una tercera de borrado.
El componente necesario para introducir sentencias SQL personalizadas es
TFDUpdateSQL. Este se conecta con el TFDQuery a través de la propiedad
UpdateObject de este último. Las propiedades clave de TFDUpdateSQL
son:
InsertSQL: Contendrá la sentencia SQL a utilizar para introducir nuevas
filas en la tabla. Los valores a insertar se referencian mediante la sintaxis
NEW nombrecolumna.
ModifySQL: Esta propiedad aportará la sentencia SQL que se usará para
actualizar datos existente en la tabla. Además de referencias a los nuevos
valores, con la sintaxis antes indicada, normalmente también serán pre-
cisos valores recuperados con anterioridad, en la consulta previa a la actua-
lización, para componer la cláusula WHERE. Dichos valores son accesibles
mediante la sintaxis OLD nombrecolumna.
DeleteSQL: Almacenará la sentencia SQL encargada de eliminar filas
de la tabla. Esta utilizará habitualmente la clave primaria en la sentencia
WHERE a fin de afectar únicamente a la entrada que corresponda.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EDICIÓN DE DATOS 293
Además de estas tres, en ocasiones puede ser preciso utilizar también las pro-
piedades FetchRowSQL, cuya sentencia facilitarı́a la recuperación de una fila
concreta; LockSQL, con la sentencia a utilizar para bloquear una fila que va a
ser modificada, y UnlockSQL, que facilitarı́a la sentencia SQL complementaria
a la anterior.
NOTA
El componente TFDUpdateSQL puede vincularse, además de a un
TFDQuery, con los componentes TFDTable y TFDStoredProc. En
este último caso es obligado utilizar un TFDUpdateSQL, ya que el
componente TFDStoredProc no aporta sentencia de selección alguna
que facilite la generación automática del resto de sentencias SQL.
Las sentencias a almacenar en las anteriores propiedades pueden generarse
durante la ejecución y simplemente asignarse, como cadenas de texto que son.
Durante la fase de diseño, por el contrario, podemos recurrir al editor especı́fico
con que cuenta el componente TFDUpdateSQL. Veamos con un ejemplo cuáles
serı́an los pasos a seguir para configurar dicho componente a fin de poder actua-
lizar antes mostrada en el Listado 9.6. Partimos, como es habitual, de un pro-
yecto con un módulo de datos, un componente TFDConnection conectado a
la base de datos de ejemplo AdventureWorks, un TFDGUIxWaitCursor
y un TFDQuery. A partir de aquı́, el procedimiento a seguir serı́a el siguiente:
1. Agregamos al formulario un TFDUpdateSQL. Este se conectará automáti-
camente con el TFDConnection. Seleccionamos el TFDQuery, bus-
camos su propiedad UpdateObject y elegimos de la lista desplegable el
único elemento disponible. De esta forma vinculamos el conjunto de datos
con el componente que facilitará las sentencias SQL necesarias.
2. Hacemos doble clic sobre el TFDQuery para abrir el editor de consultas,
introduciendo la consulta de selección propuesta en el Listado 9.6. Podemos
ejecutarla para comprobar que el resultado es el esperado.
3. A continuación hacemos clic en el botón UPDATESQL EDITOR que hay en
el editor de consultas (véase la Figura 9.16). Si el TFDQuery está
correctamente vinculado al TFDUpdateSQL se abrirá el editor especı́fico
de este último.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
294 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
Figura 9.16 I NTRODUCIMOS LA CONSULTA Y ACCEDEMOS AL EDITOR DEL
COMPONENTE TFDUP D A T ESQL
Figura 9.17 SELECCIONAMOS LAS COLUMNAS PARA CADA CATEGOR ÍA
4. La página G ENERATE de este editor, mostrada en la Figura 9.17, nos per-
mite generar automáticamente las sentencias SQL de inserción, modificación
y eliminación. Para ello tenemos que dar los siguientes pasos:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EDICIÓN DE DATOS 295
(a) Abrimos la lista desplegable TABLE N AME y seleccionamos la tabla
a actualizar. En este caso, asumiendo que tenemos la base de datos
AdventureWorks, elegirı́amos [Link].
(b) Seleccionamos en la lista K EY F IELDS las columnas que forman la
clave primaria.
(c) Seleccionamos en la lista U PDATING F IELDS las columnas de la tabla
que se podrán actualizar.
(d) En la última lista se pueden marcar los campos que es necesario actuali-
zar tras las operaciones.
(e) Finalmente hacemos clic en el botón G ENERATE SQL.
5. Para terminar, usando la página SQL C OMAMANDS (véase la Figura 9.18)
revisamos las sentencias SQL generadas y, si es necesario, introducimos
cualquier ajuste que proceda. También podrı́amos utilizar esta página del
editor para escribir manualmente dichas sentencias, en lugar de generarlas
con los pasos previos.
Figura 9.18 AJUSTAMOS LAS SENTENCIAS SQL SI ES PRECISO
6. Pulsamos el botón OK para cerrar el editor del componente TFDUpdateSQL
y el mismo botón en el editor del componente TFDQuery cerrándolo también.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
296 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
Para comprobar la configuración que hemos definido no tenemos más que
agregar un TGrid al formulario, enlazarlo con el TFDQuery, dar el valor True
a la propiedad Active de este y ejecutar el proyecto.
9.4 Procesamiento de datos en el
servidor
En las secciones previas de este capı́tulo ya se ha mencionado la importancia
que tiene en una configuración cliente/servidor la reducción del volumen de
datos a transmitir. Una de las vı́as que tenemos para disminuir la cantidad de
información a transferir consiste en trasladar, cuando sea posible y adecuado, el
procesamiento de los datos desde el cliente al servidor.
Esta sección describe tres escenarios habituales en los que, trasladando el
procesamiento al servidor, podemos incrementar de manera notable el rendi-
miento de nuestra aplicación en la mayorı́a de los casos. Lógicamente pueden
darse multitud de excepciones. Si la comunicación entre el servidor de datos y
los clientes es de alta capacidad y velocidad pero, por el contrario, el servidor de
datos está saturado por la cantidad de solicitudes a procesar, las técnicas descritas
a continuación serı́an contraproducentes.
9.4.1 Agrupación y agregado de datos
Siempre que necesitemos resultados agregados y/o agrupados de los datos que
aloja una base de datos, en general será mucho más eficiente dejar el trabajo
en manos del RDBMS que trasladar todas las filas de datos hasta el cliente y
efectuar los cálculos en este.
El método posiblemente más eficiente para conseguir datos agrupados y agre-
gado a partir de una consulta sea creando una vista en el RDBMS. Esta se alma-
cenará ya analizada y compilada en el servidor de datos, pudiendo consultarse
como si de una tabla real se tratase. No obstante, si no tenemos privilegios para
crear este tipo de objeto en la base de datos o el RDBMS no los soporta, siempre
podemos recurrir a enviar directamente la consulta incluyendo las funciones de
agregado y agrupación apropiadas.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
PROCESAMIENTO DE DATOS EN EL SERVIDOR 297
Supongamos que necesitásemos obtener el precio medio para cada subcate-
gorı́a de producto existente en nuestra base de datos AdventureWorks. Para
obtener esta información tenemos básicamente dos alternativas:
Ejecutar una consulta sobre la tabla de productos obteniendo el código de
subcategorı́a y precio de todas sus filas. Una vez recibidos los datos en el
cliente, este se encargarı́a de recorrer dichas filas y efectuar el cálculo.
Ejecutar una consulta en la que se soliciten los datos ya agrupados y agre-
gados, dejando que sea el RDBMS quien realice el trabajo y nos devuelva
los resultados.
Esta segunda opción es la que se pone en práctica en la Figura 9.19. En
lugar de cientos o miles de filas, tantas como productos existan en la base de
datos, se recibe solo una fila por subcategorı́a incluyendo ya el precio medio. El
volumen de datos transferidos por la red, ası́ como el procesamiento efectuado
en el cliente, se reducen drásticamente.
Figura 9.19 SOLICITAMOS AL SERVIDOR LOS DATOS AGREGADOS Y AGRUPADOS
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
298 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
9.4.2 Otros cálculos sobre los datos
Cuando los cálculos a efectuar sobre los datos no se limitan a sumas, conteos y
promedios, que es lo que nos ofrecen las funciones de agregado de SQL, puede
parecer que la única alternativa consiste en trasladar toda la información hasta el
cliente para que este pueda elaborar los resultados que se necesitan. Existe, no
obstante, una alternativa: la creación en el RDBMS de las funciones apropiadas
para efectuar dicho trabajo.
La mayor parte de los RDBMS contemplan la definición de funciones que,
aceptando un conjunto de parámetros variable como entrada, pueden acceder
al contenido de las tablas, ya sea mediante consultas o con cursores, y realizar
prácticamente cualquier cálculo sobre los datos y devolver un resultado. Este
puede ser un valor escalar, por ejemplo un número, o bien un conjunto de filas y
columnas, según los casos.
Imaginemos que queremos trasladar a una función la obtención de los códigos
de subcategorı́a de productos con sus respectivos precios medios, el mismo resul-
tado que obtenı́amos anteriormente con una consulta, pero limitando las filas
obtenidas a aquellos casos en los que el precio medio supere un cierto lı́mite.
El supuesto podrı́a ser más complejo e implicar el uso de construcciones más
elaboradas del lenguaje T-SQL de SQL Server, pero aquı́ nos centramos es-
pecı́ficamente en cómo utilizar la función desde Delphi. El primer paso serı́a
abrir la base de datos AdventureWorks y ejecutar el siguiente código para
crear la función:
1 CREATE FUNCTION HighPriceCategories (@LimitPrice money)
2 RETURNS @HighPricesTable TABLE (
3 SubCategoryId int,
4 AveragePrice money
5 )
6 AS
7 BEGIN
8 INSERT @HighPricesTable
9 SELECT [Link],
10 AVG([Link]) As AveragePrice
11 FROM [Link] AS S
12 INNER JOIN [Link] AS P
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
PROCESAMIENTO DE DATOS EN EL SERVIDOR 299
13 ON [Link] = P.⤦
Ç ProductSubcategoryID
14 GROUP BY [Link]
15 HAVING AVG([Link]) > @LimitPrice
16 RETURN
17 END
Listado 9.7 Función para SQL Server
EJEMPLO 9.4 [Link]
Puedes encontrar este proyecto completo en la carpeta
CSFuncionSQL. Deberás ajustar el componente TFDConnection
para conectar con el servidor SQL Server y abrir la base de datos
AdventureWorks. Previamente has de crear la función mostrada en
el Listado 9.7 en dicha base de datos, ya sea desde el Explorador de
datos de Delphi o recurriendo al SQL Server Management Studio.
Creada la función, iniciaremos un nuevo proyecto de tipo multi-dispositivo al que
agregaremos un módulo de datos. En este insertaremos los componentes nece-
sarios para conectar con la base de datos, incluyendo un TFDQuery. Hacemos
doble clic sobre él e introducimos la consulta a ejecutar, que será la siguiente:
1 SELECT *
2 FROM HighPriceCategories(:LimitPrice)
Listado 9.8 Consulta para ejecutar la función SQL
En esta consulta se ha introducido un parámetro sustituible que es necesario
configurar. Para ello recurrimos a la página PARAMETERS del mismo cuadro de
diálogo (véase la Figura 9.20), indicando que se trata de un parámetro de entrada
hacia la función de tipo moneda y facilitando un valor por defecto. Podemos usar
el botón E XECUTE para comprobar que la consulta funciona correctamente.
La interfaz de usuario del programa contará con un TPanel ajustado a la
parte superior y un TGRid ocupando el resto del espacio disponible. Enlazare-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
300 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
Figura 9.20 CONFIGURAMOS EL PAR ÁMETRO A FACILITAR A LA CONSULTA
mos este último con el TFDQuery. En el TPanel insertaremos un TEdit, que
permitirá introducir el valor lı́mite, y un botón que se encargará de actualizar los
datos mostrados en la cuadrı́cula. Hacemos doble clic sobre el botón e introduci-
mos el código mostrado a continuación:
1 procedure TfrmMain.Button1Click(Sender: TObject);
2 begin
3 with dmFuncionSQL.FDQuery1 do
4 begin
5 Disconnect;
6 [Link](’LimitPrice’).Value := StrToInt(⤦
Ç [Link]);
7 Open;
8 end;
9 end;
Listado 9.9 Código asociado al botón de consulta
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
PROCESAMIENTO DE DATOS EN EL SERVIDOR 301
Con esto ya estamos en disposición de ejecutar el proyecto y, como se aprecia
en la Figura 9.21, introducir cualquier valor y ejecutar la consulta que invoca a
la función antes definida. El trabajo de selección y filtrado de los datos se realiza
completamente en el servidor, transfiriéndose al cliente solo unas pocas filas.
Figura 9.21 EL PROGRAMA EJECUTANDO LA FUNCI ÓN
9.4.3 Actualización de datos por lotes
La mayor parte de los programadores tienden a confiar en el c ódigo de su apli-
cación para llevar a cabo todas las tareas de inserción y actualización de datos.
Un administrador de bases de datos, por el contrario, centralizarı́a una buena
parte de la lógica de tratamiento de los datos, especialmente aquellas operaciones
repetitivas y de cierta complejidad, en el proprio servidor de datos.
En aquellos casos en los que es necesario actualizar lotes de datos, aplicando
la misma operación a cada fila a fectada, p odemos m ejorar l a e xperiencia del
usuario si en lugar de transferir los datos hasta el cliente, modificarlos en este y
enviarlos de vuelta al servidor, efectuamos el trabajo directamente en este último.
Para ello lo habitual es recurrir a la ejecución de procedimientos almacenados,
bloques de código similares a las funciones pero que no han de devolver nece-
sariamente un resultado.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
302 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
NOTA
La cláusula SET de una sentencia SQL UPDATE puede incluir cálculos
y referencias a otras columnas, por lo que operaciones de actualización por
lotes básicas, como puede ser la modificación de una columna en un cierto
porcentaje o la asignación de un valor obtenido a partir de cálculos sobre
otras columnas, no precisan el uso de procedimientos almacenados.
Para ejecutar un procedimiento almacenado recurriremos habitualmente al
componente TFDStoredProc. El nombre del procedimiento almacenado se
facilitará en la propiedad StoredProcName. En el caso concreto de SQL
Server, las propiedades CatalogName y SchemaName aportarán el nombre
de la base de datos y el esquema, datos que pueden introducirse directamente
en el nombre como prefijos separados por puntos. Para ejecutar el procedi-
miento uspGetManagerEmployees del esquema dbo de la base de datos
AdventureWorks, por ejemplo, podrı́amos usar las tres propiedades o bien
asignar el valor [Link] a
la propiedad StoredProcName.
La mayorı́a de las veces el procedimiento almacenado a ejecutar necesitará
algún parámetro de entrada. Estos se facilitarán, como es habitual, mediante la
colección Params del componente. Es una operación que podemos efectuar
en la fase de diseño, mediante el editor asociado, o bien en ejecución, como se
mostraba en el ejemplo previo al ejecutar una función.
9.5 Ejecución de scripts SQL
A pesar de que el componente TFDConnection nos permite, a través del
método ExecSQL, ejecutar sentencias SQL, algo que también podemos hacer
de forma general mediante el componente TFDQuery, en ocasiones podemos
encontrarnos con ciertas limitaciones. Determinados RDBMS no permiten usar
por esta vı́a algunos tipos de sentencias, como las de definición de estructuras de
datos. Tampoco se suele permitir la declaración de variables, uso de cursores y
otras técnicas habitualmente reservadas para los scripts SQL.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EJECUCIÓN DE SCRIPTS SQL 303
Para poder ejecutar un script SQL desde una aplicación Delphi lo más cómodo,
salvo que tengamos el código del script implementado en el RDBMS como un
procedimiento o función que podamos ejecutar directamente, es recurrir al
componente TFDScript. Este ofrece una vı́a para ejecutar scripts SQL bajo el
control de nuestro programa.
En esta sección se explica, y también se demuestra mediante un ejercicio simple,
c ómo utilizar el componente TFDScript para ejecutar guiones SQL desde nuestra
aplicación.
9.5.1 Vı́as para aportar el c ódigo SQL a ejecutar
Las sentencias SQL que componen el guión a ejecutar pueden entregarse al
componente TFDScript por distintas vı́as, de las cuales elegiremos la que más nos
convenga en cada caso. Dichas alternativas son:
En un archivo: Es habitual almacenar los guiones SQL, especialmente
cuando son relativamente extensos, en un archivo independiente. Este suele
tener extensión .sql. Podemos asignar la ruta y nombre del archivo a
la propiedad SQLScriptFileName del componente, distribuyendo el
guión junto con la aplicación. Esto también nos permitirı́a alterar el código
SQL sin necesidad de modificar el proyecto.
En una colección de cadenas: La propiedad SQLScripts del compo-
nente TFDScript puede contener una colección de objetos, cuya clase
es TFDSQLScript, compuesto cada uno de ellos de un nombre y una
colección de cadenas de texto (propiedad SQL) pensadas para almacenar las
sentencias del script. Esta propiedad puede ser editada tanto en la fase de
diseño (véase el siguiente apartado) como en ejecución.
Como parámetro: Mediante el método ExecuteScript es posible eje-
cutar un script facilitándolo directamente como parámetro. El tipo del ar-
gumento de entrada es TStrings, una colección de cadenas de texto.
Como se aprecia en la Figura 9.22, además de las dos propiedades ya citadas
el componente TFDScript cuenta también con otras que ya conocemos, como
FetchOptions o Params, a las que se suman algunas más de carácter es-
pecı́fico, como es el caso de ScriptOptions. Esta última es un objeto de
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
304 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
clase TFDScriptOptions conteniendo una extensa lista de propiedades que
determinan la forma en que se ejecutará el script. Por regla general los valores
por defecto serán los adecuados.
Figura 9.22 PROPIEDADES DEL COMPONENTE TFDSC R I P T
NOTA
El componente TFDScript reconoce la sintaxis para scripts SQL de los
RDBMS más populares, incluyendo SQL Server, Oracle, Interbase, Firebird
y MySQL.
9.5.2 Edición y prueba del guión en la fase
de diseño
Mientras nos encontramos en el diseñador de Delphi podemos probar los guiones
SQL que pretendemos utilizar usando las dos primeras vı́as de las tres antes
citadas. En la primera bastarı́a con facilitar el nombre del archivo con el guión.
En la segunda tendremos que abrir el editor especı́fico asociado a la propiedad
SQLScripts, haciendo a continuación clic en el primer botón para añadir al
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EJECUCIÓN DE SCRIPTS SQL 305
menos un elemento. Este se abrirá de inmediato en el Inspector de objetos, en el
que veremos que cuenta con dos propiedades: Name y SQL. Esta última tiene, a
su vez, un editor especı́fico que será el que utilicemos para introducir el guión,
tal y como se muestra en la Figura 9.23.
Figura 9.23 EDICI ÓN DEL script SQL
Figura 9.24 OPCIONES PARA PROBAR EL GUI ÓN EN LA FASE DE DISE ÑO
Una vez que hemos introducido el guión, o indicado la ruta y nombre del
archivo, las opciones VALIDATE y E XECUTE del menú contextual (véase la
Figura 9.24) del componente TFDScript nos permiten validarlo y ejecutarlo,
respectivamente. Habitualmente, salvo que el guión genere algún error, sola-
mente veremos aparecer momentáneamente un cuadro de diálogo, sin más. Para
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
306 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
interactuar con el guión tendremos que responder a eventos de TFDScript
como OnConsoleGet y OnConsolePut. Como alternativa podemos recurrir
al componente TFDGUIxScriptDialog descrito en el siguiente apartado.
9.5.3 Asociar un cuadro de diálogo especı́fico
El componente TFDScript cuenta con los eventos necesarios para facilitar la
interacción con el guión a medida que se ejecuta. La validación y ejecución se
lleva a cabo mediante los métodos ValidateStep, ValidateAll,
ExecuteStep y ExecuteAll. Con el primero se validan paso a paso las
partes del guión, mientras que con el segundo se valida por completo. Los otros
dos ejecutan un paso o todo el guión, respectivamente. La posición actual en el
guión, útil cuando se ejecuta paso a paso, viene dada por la propiedad Position.
Si queremos aportar una interfaz gráfica que permita al usuario interactuar
con el guión, introduciendo valores si fuesen necesarios y obteniendo tanto
información sobre los errores como la visualización de los resultados, podemos
usar el componente TFDGUIxScriptDialog. Al igual que ocurre con
TFDGUIxWaitCursor, el citado componente cuenta con una propiedad
llamada Provider que determina si la interfaz será FMX, VCL o de consola.
Tras agregarlo al módulo de datos o formulario, el TFDGUIxScriptDialog
se vincula al TFDScript mediante la propiedad ScriptDialog de este último.
Con la propiedad Options del primero es posible ajustar algunas características
del funcionamiento del cuadro de diálogo.
9.5.4 En la práctica
Comprobemos con un ejercicio cuáles serı́an los pasos a seguir para introducir y
ejecutar un script SQL desde un programa. Iniciamos un proyecto de tipo multi-
dispositivo, agregamos un módulo de datos e introducimos en el un componente
TFDConnection configurándolo para acceder a la base de datos SQL Server
AdventureWorks. Incluimos también un componente TFDGUIxWaitCursor,
un TFDScript y un TFDGUIxScriptDialog. Todos ellos se enlazarán
automáticamente con el TFDConnection. A continuación seguimos estos pasos:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
EJECUCIÓN DE SCRIPTS SQL 307
1. Abrimos el editor de la propiedad SQLScripts del TFDScript, hace-
mos clic en el primer botón para crear un guión y le asignamos el nombre
GetListPrice.
2. Abrimos el editor asociado a la propiedad SQL del elemento creado en el
paso anterior, introduciendo el guión SQL mostrado a continuación. Este
tiene por objetivo recuperar el precio que tenı́a un determinado producto en
una fecha dada, consultando para ello una tabla en la que están registrados
los precios históricos de todos los productos.
1 DECLARE @ListPrice money;
2
3 SELECT @ListPrice = [Link]
4 FROM [Link] p
5 INNER JOIN [Link] plph
6 ON [Link] = [Link]
7 AND [Link] = 707
8 AND ’15/08/2005’ BETWEEN [Link] AND plph⤦
Ç .EndDate;
9
10 SELECT @ListPrice;
Listado 9.10 Guión SQL para obtener el precio
3. Vinculamos el TFDScript con el TFDGUIxScriptDialog. Para ello
usamos la lista asociada a la propiedad ScriptDialog del primero. La
abrimos y elegimos el único elemento existente.
4. Desplegamos los campos de la propiedad Options correspondiente al
componente TFDGUIxScriptDialog y desactivamos ssAutoHide.
Con esto evitamos que se oculte automáticamente el cuadro de di´alogo
una vez que la ejecución del guión haya finalizado.
5. Cambiamos al formulario, que enlazaremos con el módulo de datos, y
agregamos al mismo un TButton. Este será el único elemento de nuestra
interfaz de usuario.
6. Hacemos doble clic sobre el botón e introducimos las dos sentencias si-
guientes a fin de validar y ejecutar el guión:
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
308 INTRODUCCIÓN AL DESARROLLO CLIENTE/SERVIDOR
1 procedure TfrmMain.Button1Click(Sender: TObject);
2 begin
3 [Link];
4 [Link];
5 end;
Listado 9.11 El botón validará y ejecutará el guión SQL
Ahora ya podemos ejecutar el proyecto. Al hacer clic sobre el botón que
habı́amos introducido en el formulario debe abrirse automáticamente el cuadro
de diálogo mostrado en la Figura 9.25, facilitando en la parte inferior el resultado
que ha generado la ejecución del guión SQL. Si se produjese algún error también
aparecerı́a toda la información relativa al mismo en el panel.
Figura 9.25 CUADRO DE DI ÁLOGO CON LA EJECUCI ÓN DEL SCRIPT
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
RESUMEN 309
EJEMPLO 9.5 [Link]
Puedes encontrar este proyecto completo en la carpeta CSScript. De-
berás ajustar el componente TFDConnection para conectar con el
servidor SQL Server y abrir la base de datos AdventureWorks.
9.6 Resumen
INFORMATICA PI TARCH DES CO, S.L., a lo largo de este capı́tulo hemos
conocido multitud de aspectos que es necesario tomar en consideración a la hora
de desarrollar una aplicación cliente/servidor con Delphi. Al conectar con el
RDBMS es necesario autenticarse de manera apropiada, ası́ como optimizar en
la medida de lo posible el uso que se hace de las conexiones con el servidor de
datos. También se han descrito los procedimientos a seguir para obtener y editar
datos en este contexto, ası́ como las vı́as que nos permiten realizar parte del
trabajo en el propio servidor, reduciendo la cantidad de información que es
necesario transportar por la red hasta los dispositivos que actúan como clientes.
Finalmente se ha explicado cómo ejecutar guiones SQL directamente desde
Delphi, sin necesidad de escribir funciones o procedimientos almacenados ni
recurrir a las consolas interactivas ofrecidas por cada RDBMS.
En el siguiente capı́tulo abordaremos un tema que no nos ha preocupado
hasta el momento: la gestión de transacciones. En un entorno mono-usuario,
como el de los proyectos propuestos en la primera parte del libro, este es un
aspecto que casi carece de importancia. En un contexto cliente/servidor, por el
contrario, resulta vital.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
Capı́tulo 10
TRANSACCIONES,
BLOQUEOS Y NOTIFICACIÓN
DE CAMBIOS
Cuando una aplicación manipula la información alojada en un servidor de datos,
usando para ello sentencias SQL a través de los componentes descritos en capı́tu-
los previos, siempre lo hace en el contexto de una transacción. FireDAC cuenta
con un mecanismo de gestión de transacciones por defecto, razón por la que,
hasta ahora, no nos hemos preocupado de este aspecto.
El uso de transacciones es especialmente importante cuando se trabaja con
datos procedentes de dos o más tablas o incluso con información procedente de
bases de datos distintas. El ejemplo más tı́pico de la importancia de las trans-
acciones es el relativo a los movimientos bancarios: un usuario ordena una trans-
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
312 TRANSACCIONES, BLOQUEOS Y NOTIFICACIÓN DE CAMBIOS
ferencia desde una cuenta a otra, lo cual implica realizar dos anotaciones (dos
modificaciones sobre la base de datos), la primera con el cargo en la cuenta de
origen y la segunda con el abono en la cuenta de destino. Si se produjese algún
tipo de fallo entre ambas operaciones el estado de la base de datos serı́a incon-
sistente.
El objetivo de este capı́tulo es exponer la utilidad de las transacciones y la
forma en que se gestionan al trabajar con bases de datos mediante los compo-
nentes de FireDAC. Comenzaremos conociendo las propiedades que aporta una
transacción, para a continuación distinguir entre el control de transacciones ofre-
cido por el RDBMS, accesible desde los guiones SQL, y el propio de FireDAC,
de nivel más genérico.
10.1 Introducción al uso de
transacciones
En las ocasiones en que una operación lógica sobre los datos implica la eje-
cución de múltiples operaciones fı́sicas sobre la información almacenada en la
base de datos, hay multitud de situaciones de este tipo similares a la mencionada
antes relativa a la transacción bancaria, el uso de transacciones resulta indispen-
sable.
Esta sección introduce los fundamentos relativos al uso de transacciones en
un RDBMS, enumerando las propiedades que aportan y las operaciones básicas
de control.
10.1.1 Propiedades de una transacción
El correcto uso de transacciones durante el desarrollo de una aplicación clien-
te/servidor aportará las siguientes propiedades:
Atomicidad: La atomicidad de una transacción garantiza que la operación
logica sea tratada como una sola operación fı́sica, de forma que se
completen todos sus pasos o ninguno de ellos. No existe la posibilidad de
que la transacción quede a medias.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
INTRODUCCIÓN AL USO DE TRANSACCIONES 313
Consistencia: Esta propiedad garantiza el cumplimiento de todas las re-
glas aplicables a las operaciones que sean ejecutadas en el contexto de la
transacción. Estas pueden ser restricciones de dominio, ejecución de desen-
cadenadores, etc.
Aislamiento: Las operaciones intermedias efectuadas en una transacción
no son visibles para el resto de las transacciones, de forma que cada una
se ejecuta de manera aislada respecto a las demás. Únicamente cuando una
transacción se completa los cambios efectuados sobre los datos son visibles
para el resto.
Durabilidad: La durabilidad de una transacción es la propiedad que garan-
tiza que, una vez se haya concluido y confirmado, los cambios efectuados en
los datos serán perdurables incluso si se produjese cualquier fallo posterior
que pudiera afectar a la base de datos. Para ello cada RDBMS suele con-
tar con un mecanismo propio que, paralelamente a la propia base de datos,
mantiene un registro de las operaciones aplicadas.
NOTA
Las propiedades que acaban de enumerase suelen conocerse por el
acrónimo ACID, formado por la inicial de cada propiedad en inglés:
Atomicity, Consistency, Isolation y Durability.
10.1.2 Operaciones de control de una transacción
Todos los RDBMS que contemplan el uso de transacciones, entre los que se
incluyen todos los que soportan conexiones remotas y, por tanto, pueden ser
usados en una configuración cliente/servidor, ofrecen un mecanismo de control
de transacciones basado en las tres siguientes funciones:
Inicio de la transacción: Marca el punto a partir del cual las sentencias
SQL serán consideradas parte de una transacción. Dependiendo del RDBMS
esta operación se efectuará con la orden START TRANSACTION, BEGIN
TRANSACTION o similar.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
314 TRANSACCIONES, BLOQUEOS Y NOTIFICACIÓN DE CAMBIOS
Confirmación de la t ransacción: Tras facilitar la secuencia de sentencias
SQL que han de ejecutarse dentro de la transacción, esta se confirma para
completar la ejecución. La sentencia más habitual en los RDBMS para esta
operación es COMMIT.
Cancelación de la transacción: Si durante la ejecución de las sentencias
SQL que forman la transacción se produce algún fallo, la transacción
completa es cancelada de forma que ninguna de las operaciones se aplica
finalmente. La sentencia más habitual para esta operación es ROLLBACK.
Dependiendo de cada RDBMS las transacciones podrán anidarse o no, se con-
templará el uso de transacciones continuas, etc.
10.2 Transacciones de base de datos
vs transacciones FireDAC
Al desarrollar una aplicación cliente/servidor con Delphi y FireDAC tendremos
fundamentalmente dos alternativas a la hora de usar transacciones: recurrir a
las sentencias del RDBMS que vaya a utilizarse o bien confiar en el mecanismo
ofrecido por FireDAC para esa misma tarea. En realidad estas dos opciones no
son excluyentes entre sı́.
Para utilizar el mecanismo de control de transacciones del RDBMS lógicamen-
te debemos conocer las sentencias especı́ficas que este ofrece, ya que estas varı́an
según el producto. En contraposición, FireDAC nos ofrece una interfaz unificada
para gestionar las transacciones. Será el componente TFDConnection el que
se encargue, según el tipo de RDBMS al que esté conectado, de traducir nuestras
acciones al conjunto de sentencias adecuado.
En general podemos encontrarnos con dos situaciones diferentes en las que
utilizarı́amos las transacciones de la base de datos o las de FireDAC:
Al ejecutar scripts SQL, ası́ como el interior de funciones, desencadenadores
y procedimientos almacenados, recurriremos al mecanismo de control de
transacciones ofrecido por el RDBMS.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
CONTROL DE TRANSACCIONES EN FIREDAC 315
Al operar sobre los datos con componentes como TFDQuery o TFDTable
el método preferente de control de transacciones será el que nos ofrece
FireDAC.
En la siguiente sección centramos nuestra atención sobre el procedimiento de
control de transacciones propio de FireDAC que, como programadores, será el
que habitualmente usemos con mayor frecuencia.
10.3 Control de transacciones en
FireDAC
FireDAC nos ofrece un mecanismo de control de transacciones de alto nivel,
capaz de operar de forma autónoma como hemos podido comprobar en los ejer-
cicios del capı́tulo previo, en el que en ningún caso hemos iniciado, confirmado o
cancelado una transacción. Este sistema automático de control de transacciones,
no obstante, también tiene sus limitaciones, de ahı́ que exista la posibilidad de
aplicar un control manual sobre el estado de las mismas.
En esta sección se explican las diferentes alternativas que tenemos a nuestro
alcance, ası́ como los componentes, propiedades y métodos implicados en cada
una de ellas.
10.3.1 Transacciones automáticas
El modo de trabajo de FireDAC consiste en iniciar automáticamente una
transacción antes de ejecutar cualquier sentencia de actualización de datos
(entiéndase inserción, modificación o eliminación), confirmándola o
cancelándola dependiendo de que la sentencia SQL pueda ser finalmente
ejecutada de forma satisfactoria o no.
El comportamiento de las transacciones automáticas viene determinado por
los valores asignados a los distintos campos de la propiedad TxOptions del
componente TFDConnection (véase la Figura 10.1). Como puede apreciarse,
la mayor parte de ellas son booleanas.
Programación de Aplicaciones Delphi con Acceso a Bases de Datos Danysoft
316 TRANSACCIONES, BLOQUEOS Y NOTIFICACIÓN DE CAMBIOS
Figura 10.1 PROPIEDADES QUE CONTROLAN LA GESTI ÓN DE TRANSACCIONES
Por defecto la propiedad AutoCommit siempre tendrá el valor True, activan-
do ası́ el mecanismo de gestión automático de transacciones. La mayor parte de
RDBMS contempla este modo automático, pero hay excepciones como es el caso
de InterBase. En estos casos FireDAC puede simular ese funcionamiento auto-
mático mediante las propiedades AutoStart, AutoStop y StopOptions.
Las dos primeras indican si ha de iniciarse y concluirse cada transacción de
forma automática, mientras que la última determina en qué caso se finalizará la
transacción. Lo habitual es que activemos las opciones xoIfAutoStarted y
xoIfCmdsInactive, de forma que la transacción solamente se finalice si fue
iniciada automáticamente, lo que implica que la propiedad AutoStart tenga
el valor True, y siempre esperando a que todos los comandos asociados a la
conexión estén inactivos, es decir, no haya ninguna operación en curso.
Las transacciones automáticas son cómodas, ya que no tenemos que preocu-
parnos de su control, pero a cambio tienen algunos inconvenientes. Los dos
fundamentales son la peor eficiencia del servidor de datos, sobre todo cuando se
ejecutan muchas operaciones sobre e