FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
|||
|
|||
dbExpress - ClientDataSets anidados
Amigos
Tengo 2 tablas sql: Maestro ID (autoinc, integer, PK) Campo1 (varchar(20)) Detalle ID (autoinc, integer, PK) IDMaestro (integer, FK al Maestro) Campo1 (varchar(20)) Mi problema es que al crear un nuevo detalle, al campo Detalle.ID se le asigna el valor de Maestro.ID, en vez de asignarseloa a Detalle.IDMaestro. Si resuelvo esto a mano de la siguiente forma: CDSDetalle.FieldByName('IDMaestro').AsInteger := CDSMaster.FieldByName('ID').AsInteger ; CDSDetalle.FieldByName('ID').AsInteger := FID ; Dec( FID ); me da error "No corresponding master record found" ya que cambié a mano Detalle.ID.... Mi pregunta es... cómo rompo esta relacion Maestro.ID = Detalle.ID y la cambio por Maestro.ID = Detalle.IDMaestro ??? Saludos Pablo |
#2
|
|||
|
|||
Hola,
no se cual es el código SQL con el que has realizado la relación, pero te tengo que decir que puede ser un problema para la relación CDS de maestro-detalle si en la tabla de detalle existe un campo que se llama igual que el campo clave de la tabla maestra y no es este campo el de relación maestro-detalle. Te lo digo por que a mi me paso y me volvia loco hasta que encontre que este era el problema. Tuve que cambiar los nombres de los campos y relacionarlos con el mismo nombre. Un saludo |
#3
|
|||
|
|||
La consulta es:
Master.sql = Select * from master where id=152 Detail.sql = Select * from detalle where idmaster = :id O sea que la relacion es Master.id = detalle.idmaster Todas mis tablas tienen un campo ID autoinc PK, para identificar a cada uno de los registros, y los fk son ID+el nombre de la tabla, por ej, IDMASTER. Lo que pasa, que el CDS (o el DSP?) ve que los 2 tienen el campo ID y los asocia en base a ese campo, pensando que es el campo FK. Saludos |
#4
|
||||
|
||||
Cita:
Cita:
Pablo: Yo utilizo un estilo de nombres similar para los campos llaves, pero eso puede ocasionar el problema que explicas al usar conjuntos de datos anidados. El problema tiene que ver con el método TDataPacketWriter.AddFieldLinks de la unidad Provider, el cual se encarga de establecer la relación de campos maestro-detalle a nivel del "paquete" de datos. Pero el "culpable" en sí no es él, sino el método GetDetailLinkFields de la mayoría de los componentes de acceso a consultas SQL, como por ejemplo TCustomSQLDataSet:
(por cierto, ¿qué componentes estás usando del lado del proveedor?) De una forma por demás simple, todos los componentes query nativos asumen que los parámetros de relación (campos maestros) llevan el mismo nombre que los campos detalles a los cuales se aplica el Where. Por ello ocurre la incorrecta asignación que reportas, la cual no puede ser solucionada como lo intentaste porque el campo ID detalle ya viene incorrectamente "marcado" desde el proveedor como campo de relación. Este problema ha sido reportado al fabricante desde el año 2002, sin que éste haya proporcionado aún una solución nativa (puede que Borland y Embarcadero estén muy apegadas al redundante estilo Customer.IDCustomer y no estimen gran cosa al elegante Customer.ID ). No obstante, en su sitio Web puedes encontrar dos temas que hablan del mismo problema, y al final de los cuales se dejan entrever posibles soluciones: https://forums.codegear.com/message.jspa?messageID=2593 http://qc.embarcadero.com/wc/qcmain.aspx?d=1488 La primera es añadir una columna con alias a la consulta maestra:
Esto ya lo probé y funciona perfectamente. Sólo recuerda quitar las banderas pfInUpdate y pfInWhere del nuevo objeto campo, y asignarle el mismo valor que le des al campo ID. La segunda sería redefinir el método virtual GetDetailLinkFields (que para eso son los métodos virtuales), creando una clase derivada de la que estés utilizando. Es un poco más elaborada, pues habría qué pensar qué código escribir en el nuevo método para hacerlo funcionar como queremos (las ideas que se proponen en el segundo enlace no me agradan mucho que digamos). Ambas soluciones te evitarán tener que renombrar los campos, a lo cual José se vio obligado desafortunadamente (a diferencia de lo que sería un framework, una biblioteca general no debe imponer estilos de nombres). Diviso una tercera solución que sería llamar con ciertos parámetros al método AddOptParameter de la interfaz DSBase maestra, pero no lo he estudiado del todo. Espero haber ayudado de alguna manera. No dejes de retroalimentar este hilo. Al González. |
#5
|
|||
|
|||
Al!!! Sos la primer persona que entiende mi problema y me da una posible solución!! Mil gracias!!!
En realidad, no trabajo con Datasnap, sino con dbExpress, y estoy haciendo unas clases para poder heredar a partir de ellas. Me basé en este link que me sirvió muchisimo. Hice la capa de acceso a datos con un DM y un TSQLQuery y le puse TBusinessObjectDM. Luego un DM con dos TDataSetProvider y dos TClientDataSet, uno para listar todos los registros de la tabla y otro para levantar exclusivamente el registro a editar, a este DM le puse TBusinessObject. De estos 2 objetos voy a heredar el resto de mis Entidades del Negocio. Hasta acá todo bien, hasta que quise implementar un TBusinessObjectMD (master/detail) que me encontré con este problema. Por más que sea "norma", no me parece bonito nombrar un campo con el nombre de la tabla. O sea, que la tabla Clientes, tenga como ID el campo IDCliente. Al trabajar de esta forma, puedo asumir que todas las tablas tienen un campo ID que identifica a cada registro, me parece lo más coherente. Luego los fk si son nombres compuestos, como por ejemplo IDMASTER para apuntar a la tabla MASTER. No soy muy amigo de redefinir métodos ni de persistir campos, así que voy a ver de "automatizar" las ProviderFlags, especificandole al DM la FK. Lo que me está frenando ahora es que no puedo hacer Select *, id as idmaster from master where id=123 Alguna idea? no quiero tener que andár poniendo todos los campos en el sql (porque si agrego un campo a la tabla, tengo que andar tocando en varios lugares) Tambien me pasaron una solución que es utilizar otro componente al que se le puede especificar la relación, pero no me puse a verlo:
Bueno, me tomé mi tiempo para responder, quise ponerle la misma dedicación que le pusiste! Ahora ya estoy encaminado y salí del pozo en el que estaba desde hace unos dias y no me permitia dormir... voy a ponerme a analizar cual es la mejor solución y la comparto. Saludos! Pablo |
|
|
Temas Similares | ||||
Tema | Autor | Foro | Respuestas | Último mensaje |
ClientDataSets y Firebird | Walterdf | Conexión con bases de datos | 19 | 27-08-2010 20:41:31 |
Capturar errores - ClientDataSets | rochi | Providers | 3 | 22-11-2008 00:05:17 |
ClientDataSets con parámetros, no funciona la consulta | rochi | Providers | 3 | 10-10-2008 20:47:24 |
ClientDataSets- Personalizar errores | rochi | Conexión con bases de datos | 0 | 03-05-2008 06:47:52 |
Clientdatasets anidados con ADO | Johnny Q | Conexión con bases de datos | 4 | 03-11-2005 02:53:25 |
|