Siempre depende (maldita sea la informatica, siempre hay grises y casi nunca blancos y negros)
Si queres referenciar al DBGrid para cambiar el color del texto, la fuente, o esas "pavadas", si, es correcto que conozcas a Form2
Si queres filtrar los datos que muestra el DBGrid, ordenarlos, refrescarlos, editar, insertar, borrar, mejor referenciar al DataModule
Cuando conectaste los componentes:
1. Creaste un ZQuery en el DataModule
2. Creaste un DataSource en el Form
3. Conectaste el DataSource con el ZQuery, usando la propiedad DataSet
4. Conectaste el DBGrid con el DataSource ,
Es decir que los datos que muestra el DBGrid son los que trajo el ZQuery en el DataModule. El DBGrid no tiene una copia de los datos
Esto es cierto porque DBGrid.DataSource.DataSet = ZQuery
Son la misma cosa
Imaginate que un invasor marciano va y te cambia el ZQuery, y ejecuta un SELECT * FROM OtraTabla. Eso va a provocar que tu DBGrid se refresque y muestre los datos de OtraTabla
Por qué es mejor acceder por el DataModule y no usando DBGrid.DataSource.DataSet?
Hay muchas razones.. con el tiempo vas a ir aprendiendo lo que es desacoplar el diseño (separar interfaz grafica, de logica de negocio, de acceso a datos), escribir codigo facil de mantener, facil de testear
Pero por lo pronto hay dos pequeñas, muy pequeñas curiosidades que te pueden servir de "fundamento"
1. Es mas engorroso escribir DBGrid.DataSource.DataSet que DataModule.ZQuery:
Si, parece una estupides, pero luego tienes un if con una condicion or y hay que evaluar dos campos, y te queda esto:
if (DBGrid1.DataSource.DataSet.FieldByName('Edad').AsInteger > 30) and DBGrid1.DataSource.DataSet.FieldByName('Edad').AsInteger < 35)
No es mucho código para una linea? Casi que no entra en el monitor! A mi siempre me molesto escribir mucho codigo en una linea, definitivamente siento que estoy haciendo algo mal. Es propenso a errores, dificil de leer.
Si, por ejemplo ahi me falto un parentesis en la segunda condicion (justo despues del and) y esto resulta en una falla de compilacion (por suerte). Y que pasa si se trata de operaciones logicas encadenadas, o matematicas, en donde ese parentesis que omiti me cambia el resultado? Como era eso de darle martillazos al monitor?
Es cierto que se puede hacer esto:
if (DBGrid1.DataSource.DataSet.FieldByName('Edad').AsInteger > 30) and (DBGrid1.DataSource.DataSet.FieldByName('Edad').AsInteger < 35)
Pero aun asi me sigue molestando a la vista, a mi me marea
Se puede mejorar usando variables a modo de alias:
var DataSet: TDataSet; begin DataSet := DBGrid.DataSource.DataSet; if (DataSet.FieldByName('Edad').AsInteger > 30) and (DataSet.FieldByName('Edad').AsInteger < 35) end:
Ok mucho mejor! Pero tiene otro problema que es parte del punto 2
2. En el ultimo codigo del ejemplo anterior se ve clarito: Estamos usando un TDataSet
Cual es el problema? Bueno, que las clases especializadas de TDataSet, agregan un monton de metodos y propiedades que no podes usar si referencias el objeto como TDataSet. Veamoslo en accion
Siempre ten en cuenta que un TZQuery es un TDataSet "mejorado"
Con un TZQuery, podes escribir este codigo:
ZQuery.SQL.Text := ' SELECT * FROM Personas ';
Intenta escribir eso con un TDataSet. No se puede! es mas, TDataSet es una (clase abstracta)
Por lo tanto, si tenes un TDataSet, no podes usar ninguno, de los metodos especificos de TZQuery. Por ejemplo, tiene propiedades para indicar el orden (SortType, SortFields)
Tiene solucion? Si, se puede aplicar una tecnica llamada casting
Que es el casting? Es agarrar un objeto y "transformarlo" en otro (ok en realidad no se transforma nada, simplemente accedemos a el como "otra cosa"). Por ejemplo
TZQuery(DBGrid.DataSource.DataSet)
Ahora si.. podes escribir todo eso y ahora tenes el TZQuery y sus metodos y propiedades. Podes ejecutar SQL, ordenar.. pero porque es malo? Primero, porque volvemos a lo mismo, alarga el codigo. Imaginate una serie de sentencias asi:
TZQuery(DBGrid.DataSource.DataSet).SQL.Text := 'bla bla bla' TZQuery(DBGrid.DataSource.DataSet).Sort := bla bla bla TZQuery(DBGrid.DataSource.DataSet) TZQuery(DBGrid.DataSource.DataSet) TZQuery(DBGrid.DataSource.DataSet)
Estas condenado a escribir TZQuery(DBGrid.DataSource.DataSet) !! A quien le gusta escribir todo eso!
Pero tiene otro problema mas grave:
El compilador no valida nada (cuidado!, no es una falla de los compiladores). Aunque te parezca mentira, este codigo compila
TZQuery(DBGrid)
Se puede castear un DBGrid para que sea un TZQuery? Como poder "se puede", pero obviamente te explota un error en tiempo de ejecucion el instante que se ejecuta esa linea de codigo
Quiere decir que, el dia de mañana, agarras tu modulo de datos, cambias el ZQuery por otro componente (porque te diste cuenta que salio una nueva version de los componentes PepitoSQL que son super rapidos y ofrecen funcionalidad X, que bien!! pongamos los componentes PepitoSQL!)
Pero te olvidaste de esto:
TZQuery(DBGrid.DataSource.DataSet)
Y como te digo, el compilador no te avisa de nada
----
En cambio, si pones los componentes en el DataModule, tu codigo siempre queda asi:
DataModule.ZQuery. .... // cambiamos los componentes ZEOS por los PepitoSQL, eliminamos "ZQuery1" del DataModule, ponemos un "PepitoQuery1" // BOOM error de compilacion DataModule.ZQuery1 no existe, ahh menos mal, hay que cambiarlo asi: DataModule.PepitoQuery1. ...
Si bien son "argumentos con sustento", esto es apenas, apenas la punta del iceberg y solo el tiempo y la experiencia (y las cagadas que nos mandamos ) los que nos enseñan
Te invito a leer codigo de terceros (sobre todo bibliotecas), ver como funcionan, porque lo hacen de esa manera "complicada", lee libros, lee sobre patrones de diseño, aprende sobre unit testing, ve seminarios online gratuitos y de calidad como los de este tipo, o este
Otra búsqueda en YouTube puede arrojar mas resultados
Editado por Agustin Ortu, 29 marzo 2016 - 02:59 .