Ir al contenido



Foto

Conexion con BB.DD sqlite


  • Por favor identifícate para responder
90 respuestas en este tema

#81 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 585 mensajes
  • LocationArgentina

Escrito 29 marzo 2016 - 02:54

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: 
 


delphi
  1. 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:
 


delphi
  1. if (DBGrid1.DataSource.DataSet.FieldByName('Edad').AsInteger > 30) and
  2. (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:
 


delphi
  1. var
  2. DataSet: TDataSet;
  3. begin
  4. DataSet := DBGrid.DataSource.DataSet;
  5. if (DataSet.FieldByName('Edad').AsInteger > 30) and (DataSet.FieldByName('Edad').AsInteger < 35)
  6. 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:
 


delphi
  1. 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
 


delphi
  1. 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:
 


delphi
  1. TZQuery(DBGrid.DataSource.DataSet).SQL.Text := 'bla bla bla'
  2. TZQuery(DBGrid.DataSource.DataSet).Sort := bla bla bla
  3. TZQuery(DBGrid.DataSource.DataSet)
  4. TZQuery(DBGrid.DataSource.DataSet)
  5. 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
 


delphi
  1. 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:
 


delphi
  1. 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:
 


delphi
  1. DataModule.ZQuery. ....
  2.  
  3. // cambiamos los componentes ZEOS por los PepitoSQL, eliminamos "ZQuery1" del DataModule, ponemos un "PepitoQuery1"
  4. // BOOM error de compilacion DataModule.ZQuery1 no existe, ahh menos mal, hay que cambiarlo asi:
  5. 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 .

  • 1

#82 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 585 mensajes
  • LocationArgentina

Escrito 29 marzo 2016 - 05:54

Por cierto, este enlace del blog de Al Gonzalez tambien es digno de leer


  • 0

#83 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 250 mensajes

Escrito 30 marzo 2016 - 10:43

Impresionante Agustin, para escribir varias paginas de un libro con sabios conocimientos. A Igual que Delphius me demostrais que gente  como vosotras se pueden aprender y avanzar sin "miedo" en esto de la programación Delphi/Lazarus.

 

Resumiendo me queda claro, que al trabajar con BB.DD cree un DATAMODULE1 con (componentes bb.dd)

Insertar en el Form donde está la DBGrid el DATASOURCE.

y trabajar con el Datamodule1.Componente igual que si fuera  DBGrid.DataSource.DataSet ZQuery.

 

Aun me quedan muchas preguntas que se generan en mi cabeza?

 

1) Si el DATASOURCE en vez de estar en el mismo FORM del DGBRid lo pongo en el DATAMODULE1? sería lo correcto? en el blog de Al González según leí es lo apropiado. Lo eliminé del Datamodule1 inicial porque ensayo-error.

 

2) Como trabajo en el mismo o distinto procedure si tengo varias "tablas" (personas, pedidos, etc....), se deben crear TZQUERY1, TZQUERY2 en el Datamodule1 o crear otros y si fueran varios DBGRid....

 

En fin estas cosas según vayan saliendo iré enfrentándome con ellas....

 

Tomo nota en sentido literal de la frase, ya que todo y digo todo, es guardado en mi cuaderno de aprendizaje...

 

Gracias amigo!

Un saludo


  • 0

#84 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 585 mensajes
  • LocationArgentina

Escrito 30 marzo 2016 - 11:44

El DataSource tranquilamente puede estar en el DataModule

 

Simplemente cuando asignas la propiedad en el DBGrid, te va a salir de la lista algo asi:


php
  1.   DataModule1.DataSource1

Obviamente que para que funcione es necesario que en el uses, en la seccion de interface este la unidad del DataModule

 

En este punto ya es algo mas personal, a mi particularmente me gusta tener el DataSource en el Form, y el DataSet fuera del Form

 

Por otra parte, para aplicaciones pequeñas esta bien tener los DataModule con los componentes de Datos y los Form con sus DataSource e interconectar estas dos cosas

 

Pero para aplicaciones ya medianas se vuelve infeciente en varios sentidos, por ejemplo porque tenes muchos Table o Query en el DataModule pero cuando muestras un determinado formulario necesitas solamente uno.. O tambien te pasa que necesitas mostrar en dos formularios distinto la misma tabla pero con diferente orden o filtro (en el articulo de Al Gonzalez lo explica estupendamente)

 

Ademas te das cuenta de que "el DataModule" (asi le decia yo literalmente cuando empezaba) no es mas que una variable global (un objeto global) que se crea cuando inicia el programa y se destruye finaliza

 

Eso lo puedes verificar en las primeras lineas del codigo fuente de los proyectos Object Pascal


delphi
  1. Application.Initialize;
  2. Application.CreateForm(TDataModule1, DataModule1);
  3. Application.CreateForm(TForm1, Form1);
  4. Application.Run;

Ya mas adelante en algun punto de tu carrera te toparas con material para leer, o te toparas con situaciones en donde te das cuenta de que estas variables globales son malas (hay centenares de motivos)

 

En mi caso particular, en los proyectos, trato de minimizar al maximo las variables globales al minimo, aun asi, hay casos muy pero muy excepcionales

 

Por ejemplo, el objeto global que representa el formulario principal no podes sacarlo (al menos no en Delphi y estoy seguro que en Lazarus tampoco)

 

Tampoco podes eliminar la linea


delphi
  1. Application.CreateForm(TForm1, Form1);

Es una "limitacion" (o requisito del framework, llamalo como quieras) 

 

Ahora, a medida que vas agregando formularios y modulos de datos al proyecto, automaticamente se van a ir agregando todas las llamadas al metodo Application.CreateForm que crea el formulario correspondiente

 

Esto es malo porque por ejemplo, retrasa el inicio de tu aplicacion (hay que crear todos los formularios y modulos de datos!), se consume mas memoria (aunque no esten en pantalla visibles, estan ahi, ocultos) y ademas esta el problema de las variables globales

 

La ventaja que tiene es que obviamente es todo automatico y facil de usar, y simplemente funciona. Agregas en el uses la unidad del formulario o el modulo de datos en cuestion, y accedes mediante la variable global: Form1, Form2, DataModule1, etc

 

Este es el efecto que Delphius mas de una vez describio muy bien como: "ser un albañil de software", y no un "arquitecto de software" (que es lo realmente todos deberiamos intentar ser), y aunque nos parezca curioso, fue y sigue siendo impulsado por los entornos de desarrollo RAD (Rapid Application Development, Desarrollo de Aplicaciones Agil o Rápido) y por la industria de software en general

 

 

Y como decia mas arriba, intento mantener al minimo las variables globales y una de las primeras cosas que hago cuando creo un nuevo formulario o modulo de datos, es quitar la linea de creacion automatica (prefiero crearlo yo cuando realmente sea necesario) y tambien quitar la referencia a la variable global que esta declarada en la unidad en cuestion, es decir:


delphi
  1. unit UnitX;
  2.  
  3. interface
  4.  
  5. uses
  6. ...
  7.  
  8. type
  9. TForm1 = class(TForm)
  10. end;
  11.  
  12. var // esto lo quito!
  13. Form1: TForm1; // esto tambien!
  14.  
  15. implementation

Obviamente que ahora si quiero usar un objeto TForm1, ya no puedo simplemente escribir "Form1.Show", ya que Form1 ahora no existe mas; para eso, tengo que crearlo


delphi
  1. procedure ..
  2. var
  3. Form: TForm1;
  4. begin
  5. Form := TForm1.Create(NIL);
  6. try
  7. Form.ShowModal;
  8. finally
  9. Form.Free;
  10. end;
  11. end;

Y esto tiene mas beneficios mas alla de la memoria y la eficiencia, y es que por ejemplo el Form que creo siempre va a estar "nuevo" y no va a acarrear estado, no quedan residuos de la ultima interaccion (por ejemplo, con la tabla de clientes ordenada por nro de telefono); y no, poner un metodo Reset o similar en este tipo de escenarios no es la solucion mas elegante

 

Dicen que el tiempo es el mejor maestro, pero te va a sorprender el hecho de que cuanto mas aprendes, mas te das cuenta que menos sabes :)

 

Y por ultimo creo que este es el mejor consejo que puedo darte, tal y comente hace poco en ClubDelphi:

 

Creo que es muy importante participar de los foros como parte de la carrera de todo aquel que quiera llamarse programador;

 

Tambien es una muy buena idea publicar la mayor cantidad de codigo posible en los espacios publicos para que puedan evaluarlo, mejorarlo, criticarlo, probarlo y extenderlo.

Obviamente tambien esto implica que debemos hacer lo mismo a la inversa, es decir, no solo escribir codigo sino ver lo que otros han escrito y porque lo hacen de esa manera

 

Es una suerte para todos nosotros contar con este tipo de espacios en los que seguro va haber alguien que va a estar interesado en el mas raro de los proyectos, asi que sigo insistiendo con lo de participar en los foros, publicar nuestros trabajos, comentar lo de otros, compararlos, mejorarlos, encontrar otra forma de hacer lo mismo..

 

Otro gran ejercicio para aprender es responder a las preguntas que tienen otros.. yo de este modo he aprendido casi practicamente todo lo que se: nadie nace sabiendo, pero sentarse adelante de un monitor con la idea de "ok hoy vamos a explorar este componente, esta clase, o a probar esto.." me resulta medio extraña. En cambio, ante una duda, un error, un problema mas concreto, ya tenemos otra motivacion y ademas algo por lo que empezar

 

Un saludo ;)


Editado por Agustin Ortu, 30 marzo 2016 - 11:45 .

  • 1

#85 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 250 mensajes

Escrito 30 marzo 2016 - 01:18

No se que decir, a tus explicaciones y conocimientos que no haya dicho ya. Los que lleváis años programando en este entorno de desarrollo lo veis desde un punto de vista distinto que lo pueda ver un humilde principante. Es cierto que se escapan muchos conocimientos, técnicas o supuestos que hacen dificil pero no imposible que uno vaya por el buen camino, pero como bien dices, eso solo se podrá conseguir con el esfuerzo y experiencia que pueda ir cada uno adquiriendo a su velocidad.

 

Lo que si tengo claro, es que desde que empecé de 0 hasta ahora, los conocimientos van calando, al mismo tiempo que surgen más y más dudas, pero confío que puedan ir dando solución a las mismas. Preguntas que serán repetitivas y quizás insistentes con una misma solución pero que harán calar más en el conomiento.

 

Gracias como siempre tanto a ti, como otros muchos que se esfuerzan por ayudar al "más débil" de los principantes y animarlo a seguir porque no es fácil empezar y menos continuar :) .

 

Un saludo


  • 0

#86 Delphius

Delphius

    Advanced Member

  • Administrador
  • 5.772 mensajes
  • LocationArgentina

Escrito 30 marzo 2016 - 04:13

Agustín, que buenas palabras. No podría haberlo dicho mejor.

Comparto contigo lo de en lo posible evitar las variables globales y hasta erradicar el uso de que de forma automática se creen los forms. Lo de eliminar las variables más de una vez lo he hecho (y que alguna que otra vez continúo haciendo)

Ahora bien si quisiera hacer una pequeña observación. Las variables globales no son un problema per se... más bien se vuelven problemáticas sino no se toma el debido control. Es lo mismo lo que sucede con la relación acoplamiento/cohesión. No puedes evitar que al tirar más de un lado, te efecte el otro. La baja cohesión o el alto acoplamiento no es problemático. Se vuelve problemático en el momento en que nos dejamos desbordar por la situación. El punto está en encontrar el "punto de equilibrio" o "zona de confort" más adecuado y que mejor nos sienta o nos de mayor seguridad y comodidad de trabajar.

 

Eso no es fácil, no se domina a la primera obviamente. Y es bastante habitual encontrarnos que nuestras primeras zonas de confort ya no son las mismas, y vamos en búsqueda de otras nuevas.

 

Dooper, ¿Que más podría decirte que no haya dicho Agustín? Muy poco realmente. Tu sigue practicando y familiarizándote con los componentes. En la medida que ta surjan nuevas dudas y madures tu formación irás entendiendo el propósito y el porqué es que tal x componente o suite se diseñó de esa forma. Respecto a tu duda sobre el TDataSource, imagínate a este componente como si fuera un puente entre la parte visual del sistema y la base de datos:

 

Forms, controles visuales <=> TDataSource <=> Base de datos

 

El TDataSource no es más que un intermediario entre los componentes visuales diseñados para mostrar información de las bases de datos, o más conocidos como componente db-ware o data-ware. Estos son los DBGrid, DBNavigator, DBEdit, etc. Y en el otro extremo están los componentes diseñados para la conexión y el acceso a las bases de datos.

Hay muchas suites de acceso, las hay generales como lo es Zeos por ejemplo, y las hay específicas para un único motor. Independientemente de la suite elegida, todo componente que acceda a una Tabla, Consulta, Vista, etc, hereda de un tronco común: TCustomDataSet. A todos esos componentes xxxTable, xxxQuery xxxStoredProc, etc. se los denomina en general por DataSet. Esto es así porque todos al fin y a cabo no son más que una abstracción software de un conjunto de datos que el motor le entrega al componente.

 

Puedes tener varios componentes db-ware unidos a un único TDataSource, y este último a un TDataSet... y hasta incluso puede darse casos en los que tenemos que tener varios TDataSource vinculados a un mismo DataSet. No hay una regla que diga donde debe colocarse el TDataSource, si en los forms o en un TDataModule; como así también no hay una regla que nos diga cuantos. Cada elección tiene sus pros y contras.

Estas elecciones son las que harán de ti más un arquitecto y no tanto un albañil. En un proyecto quizá sientas más la necesidad y seguridad de que necesites tener tus DataSource en un form, en otro proyecto quizá hasta consideres ni siquiera considerar el uso de los TDataSource.

Yo ya te invité a leer el libro de la Cara Oculta de Delphi 4. Creeme que al leerlo muchas de las dudas que actualmente tienes se te irán desapareciendo.

 

Saludos,


  • 1

#87 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 250 mensajes

Escrito 31 marzo 2016 - 03:22

A raiz de lo que Agustin_ortu, me comentaba de eliminar la columnas del DBGrid, y cosa que hice, ahora me veo en la necesidad de indicarles tamaño

a las mismas, pero claro, en el editor de objeto DBGRID -> Tcolumns NO tiene nada (ninguna columna). Como puedo cambiar el tamaño de las mimas si no me deja? ya que no hay elementos.

 

Pensaba usar esta instrución en el DBGrid.Columns[0].Width:=X

 

Si creo columnas, volvemos a lo de antes, carga filas, pero no visualiza contenido de "nombre" y "edad".

 

Lo que no entiendo es como el editor de objeto puede crear columnas para el DBGrids, y como dijo agustin no es necesario que cree columnas "nombre" y "edad" como título, ya que salen directamente en la DBGrid sin necesidad de crear columnas, que función tiene Columns[X]?


  • 0

#88 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 585 mensajes
  • LocationArgentina

Escrito 31 marzo 2016 - 04:06

Las columnas se crean automaticamente bajo demanda

 

Cuando el DataSource se enlaza al DataSet, el grid se entera y crea las columnas necesarias

 

A partir de ese momento podes "actuar" y establecer propiedades como fuente, ancho, y demas yerbas


Editado por Agustin Ortu, 31 marzo 2016 - 04:08 .

  • 0

#89 jordioptima

jordioptima

    Newbie

  • Miembros
  • Pip
  • 1 mensajes

Escrito 13 diciembre 2016 - 06:21

Disculpar amigos, he leído atentamente este post ya que en teoría solucionaba mi problema, pero me ocurre lo mismo y no hay manera de solucionar el problema, supongo que ya se les acabaron las ideas...

 

Mi proyecto trabajaba con MSAccess y todo funciona bien, fue al cambiar a SQlite que no me pinta las filas en un TGrid, están relacionados los querys con livebindings con el TGrid,
En modo diseño, hago un active del query y veo las filas en el Tgrid sin problemas. Pero si cierro el query, y lo abro en runtime, el TGrid no pinta nada, ya puedo abrir o cerrar el query, pero el TGrid no pinta, y tiene la famosa propiedad defaultdrawing a true....

 

Aguna otra idea porque me puede pasar esto en sqlite? si hago lo mismo en access funciona todo ok.


  • 0

#90 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 585 mensajes
  • LocationArgentina

Escrito 13 diciembre 2016 - 10:02

Imposible decirlo sin ver código

Cambias algún parámetro de la conexión en tiempo de ejecución? Como activas el query? Lo dejaste activo en tiempo de diseño?
  • 0

#91 Delphius

Delphius

    Advanced Member

  • Administrador
  • 5.772 mensajes
  • LocationArgentina

Escrito 13 diciembre 2016 - 04:06

Disculpar amigos, he leído atentamente este post ya que en teoría solucionaba mi problema, pero me ocurre lo mismo y no hay manera de solucionar el problema, supongo que ya se les acabaron las ideas...

 

Mi proyecto trabajaba con MSAccess y todo funciona bien, fue al cambiar a SQlite que no me pinta las filas en un TGrid, están relacionados los querys con livebindings con el TGrid,
En modo diseño, hago un active del query y veo las filas en el Tgrid sin problemas. Pero si cierro el query, y lo abro en runtime, el TGrid no pinta nada, ya puedo abrir o cerrar el query, pero el TGrid no pinta, y tiene la famosa propiedad defaultdrawing a true....

 

Aguna otra idea porque me puede pasar esto en sqlite? si hago lo mismo en access funciona todo ok.

 

Hola jordioptima, ¡Bienvenido a DelphiAccess! Espero que esta comunidad se convierta en tu segundo hogar.

 

Sin ver algo de código, y de más detalles no sabría decirte cual puede ser el problema. ¿Usas Zeos, u otra suite de componentes de conexión? ¿Estamos hablando de Lazarus? Porque que yo sepa Live Bindings es algo propio de Delphi. Y lo que se ha tratado en este hilo es relacionado a Lazarus.

 

Y si bien Delphi y Lazarus tienen sus similitudes, también hay diferencias.

 

Saludos,


  • 0