Ver Mensaje Individual
  #8  
Antiguo 16-02-2004
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Reputación: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Smile GeneratorField

¡Buen día a todos!

Hola Cadetill y StartKill.

Para los que venimos de bases de datos de escritorio, muchos de estos temas son realmente de coyontura conceptual, más que de fallas en las estructuras cliente/servidor. Sin embargo, sólo desmenuzándolos como lo hacemos ahora, es cómo realmente logramos cruzar el puente hacia las bases de datos grandes.

En efecto. Al guardar un nuevo registro, el disparador se ejecuta correctamente, otorgando un valor al campo autoincrementado y actualizando el respectivo generador. Pero el servidor no tiene la obligación de decirle a la aplicación cliente: "¡Hey! Este es el valor que le di al campo, atrápalo.", jeje .

Ahora, si en la aplicación cliente se deja el registro tal como acaba de ser guardado, el campo autoincrementado (en la memoria del cliente) seguirá sin valor alguno hasta que el conjunto de datos sea reabierto. Mientras tanto, se corre el riesgo de que ese campo con valor nulo sea utilizado como parámetro por alguna de las sentencias SQL del conjunto de datos, para las operaciones de actualizar, eliminar y refrescar, trayendo como consecuencia que dichas operaciones no se realicen o se ejecuten de forma incorrecta.

Descubrí que la clase TIBCustomDataSet (padre de TIBTable y TIBDataSet) tiene una propiedad llamada GeneratorField, objeto de clase TIBGeneratorField que sirve para que el conjunto de datos se encargue de incrementar uno de sus campos en memoria, utilizando uno de los generadores de la base de datos. Con ello, se consigue que el registro tenga un valor en el campo autoincrementado antes de ser guardado en el servidor.

La propiedad GeneratorField es publicada (pública y manipulable con el inspector de objetos) en la clase descendiente TIBDataSet, la cual, tengo entendido, es la adecuada para representar a una tabla. Sin embargo, aunque ya probé la misma propiedad con un TIBTable, curiosamente ésta clase no la hace publicada, ni siquiera pública (usé el truco de molde de tipo para poder acceder a ella).

El caso en el que estoy trabajando ahora (y que ya casi está listo), es una aplicación ADO-Access que estoy emigrando a IBX-Firebird. Cambiando las clases de todos sus componentes TADOXXX por los componentes TIBXXX que corresponde.

Aquí hago un paréntesis para mencionar la manera en que cambio la clase de decenas de componentes que ya están en varias formas y módulos de datos: Abro los archivos .dfm como texto, con el editor de código hago el reemplazo (Ctrl+R) de identificadores TADOTable por TIBTable, TADOQuery por TIBQuery, etc. De tal suerte que no hay necesidad de quitar cada componente ADO de la forma, agregar cada componente IBX sustituyo y volver a establecer todas las propiedades, campos persistentes, manejadores de eventos y enlaces que los primeros componentes tenían.

La razón por la cual utilicé (por ahora) componentes TIBTable y no TIBDataSet, es precisamente para facilitar esta migración ADO-Access a IBX-Firebird, ya que la aplicación original utiliza muchos componentes TADOTable. Convertir todos ellos a TIBDataSet sería más complicado que convertirlos a TIBTable, ya que ésta última clase tiene más propiedades en común con el componente ADO señalado. Posteriormente, se utilizará TIBDataSet en los nuevos módulos, y los actuales se irán convirtiendo a esta clase paulatinamente.

Por lo pronto es para mi muy importante tener un componente TIBTable que si publique la propiedad GeneratorField. Así que crearé una clase derivada de TIBTable para ese propósito, pero con algo adicional: Que este nuevo componente busque en la lista de generadores de la base de datos, aquel cuyo nombre se forme por el nombre de la tabla junto con el nombre de uno de sus campos, bajo el formato estándar Tabla_Campo_Gen, y que de encontrar uno realice automáticamente los establecimientos necesarios en la propiedad GeneratorField, evitando así que el programador final realice dichos establecimientos manualmente tabla por tabla. Esta útil característica, que será opcional con valor predeterminado de verdadero, posteriormente la extenderé también a una nueva clase derivada de TIBDataSet.

Aquí se pone a descubierto nuevamente la necesidad de que Object Pascal cuente con herencia insertada. Ya que, aunque pueda yo centralizar la mayor parte del código de la nueva característica, no dejará de existir algo de duplicidad de código en la nueva clase derivada de TIBTable con respecto a la nueva clase derivada de TIBDataSet (las dos clases primas tendrán algo de código idéntico). Con herencia insertada, sería posible crear una nueva clase derivada de TIBCustomDataSet, que incluyera la nueva característica, y hacer de esta clase el nuevo padre de TIBTable y TIBDataSet (inserción de nuevo padre en la jerarquía de clases), logrando que éstos dos componentes heredaran automáticamente dicha característica en la biblioteca de clases que empleo, evitando así duplicidad de código.

Muchas gracias por sus aportaciones al respecto. Seguimos en contacto.

Al González .
Responder Con Cita