Es posible anidar dataset en dbexpress, utilidad muy interesante para casos de tablas relacionadas tipo master-detail. Existe buena documentación sobre esto en internet y quiero usar esta entrada como introducción a las próximas donde se ve un tema menos documentado que es el de los autoincrementales en casos de maestro-detalle.
DBExpress permite anidar DataSet para tablas de tipo maestro-detalle hasta un limite cercano a los 15 o 16 dataset, quien escribe nunca supero los 5 o 6 y en este sentido nunca tuve mayores problemas.
¿Por que yo querría trabajar con dataset anidados?
Bueno las ventajas son varias, en principio manejar todos los elementos de manera única, cosa que es una realidad, si el maestro fuera una tabla de pedidos y me paro sobre un pedido particular quiero ver, borrar, editar y añadir items de ese pedido y no de otros.
Para mejor cuando actualizo quiero una actualización en un bloque transaccional, para todo lo relacionado, maestro y detalle.
¿Como genero un conjunto de dataset maestro-detalle en delphi?
Es fácil, con un poco de practica sale como pan caliente, pero obviamente hay que relacionar varias cosas de manera ordenada así que naturalmente puede aparecer alguna complicación las primeras veces.
Una imagen, mil palabras.
La imagen anterior muestra los diferentes componentes y sus conexiones, figura en el texto de la propiedad a conectar y la flecha la dirección de conexión. Las consultas en cada uno de los datasets serian las siguientes.
SqlPedido: Select * from Pedido
SqlItemPedido: Select * from ItemPedido Where IdPedido=:IdPedido
Se observa en la consulta de SqlItemPedido un parametro, IdPedido, el parametro debe tener el mismo nombre que la columna de la tabla maestra.
Añadiendo un y solo un datasetProvider conectado al dataset maestro (En este caso sqlPedido) tenemos solucionada “la parte servidora” independientemente de si es una aplicación multicapa o no. Si fuera una simple aplicación cliente/servidor entendamos que la parte servidora son las conexiones a la base de datos, los datasets y los providers, la parte cliente son los clientsdataset involucrados.
La "Parte servidora" quedaría entonces así
Ahora llega el momento de configurar la parte cliente, aca la cosa puede ser muy simple o se puede complicar un poco depende del diseño de base de datos.
Esta seria la forma del lado cliente, dos clientdatasets uno para la tabla maestra y otro para la tabla detalle, dos datasources enlazados y dos grillas, completando dos navigators por si son necesarios y un boton para efectuar el applyUpdate que llevara los cambios a la base de datos.
Muy importante, el ApplyUpdate solo debe ejecutarse sobre el clientdataset maestro, DBExpress se encargara del detalla en el orden correspondiente según sea inserción, edición o borrado.
procedure TFrmPedido.btnApplyUpdateClick(Sender: TObject);
begin
cdsPedido.ApplyUpdates(-1);
end;
Para saber si todo va bien basta con generar los campos en el clientdataset maestro como se indica abajo.
Si se observa un campo mas con el nombre del dataset detalle del lado servidor nos quedamos tranquilos, conectamos todo bien y estamos listos para dar el toque final.
Lo que nos queda por hacer ahora es hacer apuntar en el clientDataSet detalle el DataSetField al campo sqlItemPedido del clientDataSet maestro.
Con esto es suficiente para el clientDataSet detalle, todo lo va a manejar el maestro y en el detalle solo veremos los registros correspondiente al registro maestro actual. Incluso podemos ver que dbexpress genera automáticamente en el detalle el id del maestro correspondiente.
Podemos añadir, borrar, editar y el applyUpdate que usaremos es el del clientDataSet maestro que se encargara de todo.
Hilando un poco mas fino
En aplicaciones reales algunos cosas que no debemos dejar pasar.
¿Traemos todos los detalles juntos o los traemos a medida que nos vamos desplazando por el maestro?
Esto en realidad depende de la cantidad de datos, del tamaño etc, lo importante es saber donde determinar esto y yo he encontrado sumamente útil en variedad de casos retrasar el envío del detalle en el momento que se necesite
Como muestra la figura una de las opciones del datasetProvider es poFetchDetailsOnDemand, esta propiedad determina si los detalle se envían sobre demanda o todos al mismo tiempo.
Ahora sabemos crear master-detail condición necesaria para encarar un problema un poco mas dificil y menos documentado de como combinar esto con los autoincrementales que tanto nos gustan, incluso si no fueran autoincrementales es muy probable que el IdPedido sea responsabilidad de la base de datos y no nuestra.
La manera de resolver esto y otros temas quedan para próximas entradas.
Esta seria la forma del lado cliente, dos clientdatasets uno para la tabla maestra y otro para la tabla detalle, dos datasources enlazados y dos grillas, completando dos navigators por si son necesarios y un boton para efectuar el applyUpdate que llevara los cambios a la base de datos.
Muy importante, el ApplyUpdate solo debe ejecutarse sobre el clientdataset maestro, DBExpress se encargara del detalla en el orden correspondiente según sea inserción, edición o borrado.
procedure TFrmPedido.btnApplyUpdateClick(Sender: TObject);
begin
cdsPedido.ApplyUpdates(-1);
end;
Para saber si todo va bien basta con generar los campos en el clientdataset maestro como se indica abajo.
Si se observa un campo mas con el nombre del dataset detalle del lado servidor nos quedamos tranquilos, conectamos todo bien y estamos listos para dar el toque final.
Lo que nos queda por hacer ahora es hacer apuntar en el clientDataSet detalle el DataSetField al campo sqlItemPedido del clientDataSet maestro.
Con esto es suficiente para el clientDataSet detalle, todo lo va a manejar el maestro y en el detalle solo veremos los registros correspondiente al registro maestro actual. Incluso podemos ver que dbexpress genera automáticamente en el detalle el id del maestro correspondiente.
Podemos añadir, borrar, editar y el applyUpdate que usaremos es el del clientDataSet maestro que se encargara de todo.
Hilando un poco mas fino
En aplicaciones reales algunos cosas que no debemos dejar pasar.
¿Traemos todos los detalles juntos o los traemos a medida que nos vamos desplazando por el maestro?
Esto en realidad depende de la cantidad de datos, del tamaño etc, lo importante es saber donde determinar esto y yo he encontrado sumamente útil en variedad de casos retrasar el envío del detalle en el momento que se necesite
Como muestra la figura una de las opciones del datasetProvider es poFetchDetailsOnDemand, esta propiedad determina si los detalle se envían sobre demanda o todos al mismo tiempo.
Ahora sabemos crear master-detail condición necesaria para encarar un problema un poco mas dificil y menos documentado de como combinar esto con los autoincrementales que tanto nos gustan, incluso si no fueran autoincrementales es muy probable que el IdPedido sea responsabilidad de la base de datos y no nuestra.
La manera de resolver esto y otros temas quedan para próximas entradas.
Hola hice la conexión funciona bien el maestro detalle son dos grillas una me muestra la factura y la otra me muestra los artículos de esa factura al eliminar me elimina solo el maestro que puede ser? del lado servidor en el DSProvider tilde la opción poCascadeDeletes. utilizo delphi2010 y Sql Server 2008
ResponderEliminarJeremías
jeremontegrosso@gmail.com
Me gustaria que me envies algun codigo para ver como haces los deletes con este tipo de conexion. Gracias
ResponderEliminarjeremontegrosso@gmail.com