sábado, 1 de noviembre de 2008

/resolviendo problemas en delphi



Expongo aqui algunos problemas a los que me enfenté desarrollando en Delphi 7, movida principalmente porque la información en español es prácticamente nula.

Desconozco si estos problemas fueron solucionados en las versiones posteriores.


Herencia visual

Haciendo un framework para una aplicación, estoy en la siguiente situación. El Form padre tiene un dbgrid (grilla orientada a datos provenientes de alguna sentencia SQL).
Este form es una clase base, prácticamente una clase abstracta donde se definen sus controles y eventos de manera virtual.
La grilla no tiene definido los campos porque no sabe qué tabla será mostrada, éstos campos se definirán en el formulario hijo que es donde se ejecuta la sentencia SQL.

En el formulario hijo conecto el dbgrid con la fuente de datos usando ClientDataSets. Decido borrar uno de los campos, no me interesa que se vea. Lo hago desde el visor de propiedades del objeto dbgrid de la clase heredada:

y me sale el siguiente error:

"Selection contains a component introduced in an ancestro form which cannot be deleted"



Lo raro es que los campos no estaban definidos en el Form padre, pertenecen al form heredado, tendría que poder borrarlos. El lío parece estar por lo que pude ver en cómo maneja Delphi la clase TCollection (en este caso la de los campos), por lo menos hasta esa versión.

La solución la encontré modificando a mano, el archivo .dfm. Es un archivo de texto, fácilmente editable, donde Delphi guarda el código de las clases de los componentes visuales que hay en un form.
Lo que está marcado en azul, es lo que borré, luego grabé los cambios y voilá.


Puede pasar que deban reiniciar Delphi, quizás porque en mi caso no me di cuenta que estaba conectada a la base de datos, entonces al ejecutarlo sin salir aparecía otro error. Reiniciando se soluciona.


ClientDatasets

El dataSetprovider del clientDataSet estaba unido a una ibquery, componente que tiene la consulta con parámetros. Base de datos: Firebird.
De todos modos no importa el motor de base de datos, lo que importa es como deben estar ligados los parámetros de ClientDataSet y el ibquery que realiza la consulta.

ibquery.Sql :=
'Select campo1, campo 2 From Tabla where campo1 = :campo1 or campo2 = :campo2'

Mi idea inicial era cambiar el SQL asignando diferentes valores a los parámetros segun un criterio de búsqueda (por un parámetro u otro).
Los parámetros de ambos componentes se definieron en tiempo de diseño.

Cambiaba la sentencia SQL, pero no la cantidad de parámetros definidos (dos), ya que estos no cambiaban, solo variaba los que se usaban en la sentencia SQL:
Podría ser:
'Select campo1, campo 2 From Tabla where campo1 = :campo1'
o
'Select campo1, campo 2 From Tabla where campo2 = :campo2'

Cuando cambiaba el valor de los parámetros en tiempo de ejecución salía el siguiente error : "XSQLDA index out of range"

El código problemático era:

//asigno nuevo parámetro
cdsPacientes.params.ParamByName('CI').AsString := ci_pas;

//reabro para que realice la búsqueda con el
ibquery.sql := texto_sql;
cdsPacientes.Close;
cdsPacientes.Open;


Harta de buscar en internet, y como siempre en sitios en inglés, polacos o alemanes, que no se adaptaban a la situación que desencadenó mi problema, me avive siguiendo las sábanas de código que tiene Delphi.

El error estaba en que el ClientDataSet (que es 'alimentado' por los datos de la consulta ibquery), tenía mayor cantidad de parámetros definidos que los usados en la consulta SQL del ibquery. Deben tener la misma cantidad de parámetros. Si no hay concordancia entre los que usa el SQL y los definidos en el ClientDataSet, sale error.

Para mantener los parámetros, intenté poniendo valores inexistentes en los parámetros por los cuales no deseaba buscar. Pero no entiendo porqué ofrece problemas de filtrado. Decidí sencillamente omitir los parámetros, una pena porque pierdo cierto nivel de abstracción. La idea era modificar los parámetros sin tocar la sentencia SQL.






No hay comentarios.: