Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 29-02-2012
gustavosv gustavosv is offline
Miembro
 
Registrado: mar 2008
Posts: 51
Poder: 17
gustavosv Va por buen camino
Método retorna Set de datos

Hola, hace unos días preguntaba en éste foro sobre el tema de 'Abstraccción', y las respuestas que generosamente me bridaron implican un estudio juicioso del tema, y bueno, como no solo del amor vive el hombre (hay que generar dinero), decidí tomar un camino intermedio mientras tanto.

La historia es que estoy trabajando en un proyecto de bases de datos que de antemano quiero que me sirva tanto para una empresa pequeña que solo quiera usar una BD como MS Access o para otra más grande que ya se le mida a temas como MySQL, entonces pensé en 3 capas, front al usuario (concepto visual) por un lado, unas clases que me representen las tablas de la BD y todas las acciones que se necesiten sobre ellas (segunda capa) y otras clases que encapsulen la conexión al servidor , las consultas SELECT y los CRUDs (tercera capa), pensando que en ésta última sea la única a la que tenga que 'meterle mano' al cambiar de una BD a otra.

En éste punto me enredé y lancé un hilo "Abstracción en BD" y quienes escribieron en ese post hablaron de Persistencia, ORM y enlaces muy enriquecedor que pienso leer, pero como decía, el tiempo me acosa, debo hacer entregas y tengo fecha límite, por lo que tomé un camino intermedio, decidí hacer solo 2 capas, visual y clases de tablas de la BD con sus funciones y métodos que tienen dentro de ellas las SQL usando ADO.

Ahora el asunto es que espero que el método 'BuscarListaClientes' de la clase TCliente me retorne un conjunto o set de datos, p.ej. todos los clientes de una ciudad, y no he logrado conseguirlo, he intentado que el método 'BuscarListaClientes' devuelva un DataSource, un ClientDataSet y nada me funciona. El código que anexo es para llenar un DBGrid con la lista de Agentes Comerciales de la empresa:
Código Delphi [-]
En la forma Fpedidos:
procedure TFPedidos.Button1Click(Sender: TObject);
var
  vdatos: TDataSource;
begin
  vdatos := TDataSource.Create(nil);
  vdatos := oAgenteCial.Leer(FPrincipal.oConexion.GetConexion);
  DBGrid1.DataSource := vdatos;
end;

En la clase:

function TAgenteCial.Leer(AConexion: TADOConnection): TDataSource;
var
  vCommandText: string;
  vDatos: TADOQuery;
begin
  Result := nil;
  vDatos := TADOQuery.Create(nil);
  vDataSource := TDataSource.Create(vDatos);
  vDatos.Connection := AConexion;
  vCommandText := 'SELECT venId, venNombre FROM GEN_Vendedores ';

  vDatos.SQL.Text := vCommandText;
  try
    vDatos.Active := True;
    if not vDatos.Eof then
      Result := vDatos.DataSource;
  finally
    FreeAndNil(vDatos);
  end;
end;

El problema es que no recibo el set de datos, y como decía he intentado con varios componentes y marca exception class $C0000005 access violation at 0x09-...


Alguien ha resuelto algo similar ?
Responder Con Cita
  #2  
Antiguo 01-03-2012
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Pero tal como lo esbozas no parece tener muchas posibilidades.

De entrada, el método Leer devuelve vDatos.DataSource pero a esta propiedad del objeto ADOQuery nunca le asignas nada, además de que dicha ppropiedad es para el paso de parámetros al Query. Quizá quisiste devolver el DataSource que creaste, pero, por un lado, tal objeto creado no apunta, aparentemente, a ningún DataSet y tampoco está declarado en el método. ¿De dónde sale?

Por otro lado, si lo que quieres es devolver el DataSet que creas al vuelo, ya sea directamente o através de un DataSource, entonces no puedes destruir el objeto en el mismo método, porque entonces la rutina que lo reciba obtendrá un objeto muerto.

Tendrías que dejar que sea el receptor quien se encargue de destruir al DataSet, lo cual es propenso a errores pues le dejas una responsabilidad que probablemente no deba tener.

Alguna vez hice algo parecido, basándome en código de otros, en donde lo que devuelves, no es un DataSet sino una interfaz que contiene una DataSet. Dicha interfaz estaba implementada por un descendiente de TInterfacedObject y lo que logras con eso es un recolector de basura. Esto es, el objeto se destruye automáticamente una vez que se pierden todas las referencias a él (es la idea, los detalles no los recuerdo bien ahora).

De todas formas, no es algo tampoco que vayas a hacer en un rato.

No sé yo si estás tomando el camino adecuado dada la premura de tiempo.

Tú puedes hacer aplicaciones con varias capas usando una triada

Código:
DataSet <---> DataSetProvider <---> ClientDataSet
exponiendo únicamente el ClientDataSet al cliente. Esto te permite cambiar con relativa facilidad la capa del DataSet. En una aplicación real a tres capas, el DataSet viviría en un RemoteDataModule, pero por lo mientras lo puedes colocar en un DataModule normal. Creo que alguien (¿Al González?) llamó a esto una aplicación a dos capas y media

// Saludos
Responder Con Cita
  #3  
Antiguo 01-03-2012
gustavosv gustavosv is offline
Miembro
 
Registrado: mar 2008
Posts: 51
Poder: 17
gustavosv Va por buen camino
Hola Roman, la triada DataSet <---> DataSetProvider <---> ClientDataSet la he usado con DM locales como dices, quería 'avanzar' a algo más OOP, por ello la idea en la que me embarqué, tienes razón en cuanto a que al método Leer le sobra
Código Delphi [-]
  vDataSource := TDataSource.Create(vDatos);
, he hecho varias pruebas y se me quedó pegado.

En medio de las pruebas, llegué a la conclusión de la destrucción del objeto, pero no entendía porqué ...
Cita:
Por otro lado, si lo que quieres es devolver el DataSet que creas al vuelo, ya sea directamente o através de un DataSource, entonces no puedes destruir el objeto en el mismo método, porque entonces la rutina que lo reciba obtendrá un objeto muerto.
Para mantener esa idea de trabajo, qué puedo devolver, que me permita en 'ese lado del programa' no usar componentes de ADO ? Podría devolver un TClientDataSet ?

Qué me recomiendas ...?
Responder Con Cita
  #4  
Antiguo 01-03-2012
gustavosv gustavosv is offline
Miembro
 
Registrado: mar 2008
Posts: 51
Poder: 17
gustavosv Va por buen camino
mira, llegué a la solución que muestro ...
Código Delphi [-]
en la forma FPedidos:

procedure TFPedidos.Button1Click(Sender: TObject);
var
  vSource: TDataSource;
begin
  vSource := TDataSource.Create(nil);
  vSource := oAgenteCial.Leer(FPrincipal.oConexion.GetConexion);
  if not (vSource = nil) then
    DBGrid1.DataSource := vSource;
end;

en la clase ...

function TAgenteCial.Leer(AConexion: TADOConnection): TDataSource;
var
  vQuery: TADOQuery;
  vSource: TDataSource;
begin
  Result := nil;
  vQuery := TADOQuery.Create(nil);
  vSource := TDataSource.Create(nil);
  vQuery.Connection := AConexion;

  vQuery.SQL.Text := 'SELECT venId, venNombre, venXMLClienteCons FROM GEN_Vendedores ';
  try
    vQuery.Active := True;
    if not vQuery.Eof then
    begin
      vSource.DataSet := vQuery;
      Result := vSource;
    end;
  finally
//    FreeAndNil(vQuery);
//    FreeAndNil(vSource);
  end;
end;
El problema es que como lo decías, el componente no hacía nada porque estaba mal asociado, estaba asociando el DataSource al Query y debía asociar el Query al DataSource: vSource.DataSet := vQuery;
El asunto es que queda el temita de la liberación de los objetos vQuery y vSource ...
Responder Con Cita
  #5  
Antiguo 01-03-2012
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
En todo caso, yo devolvería el DataSet en lugar del DataSource y así sólo tienes que preocuparte por la destrucción de un objeto.

De todas formas, habría que entender qué es eso de "algo más OOP". ¿A qué te refieres? Toda la VCL de delphi es OOP. Un DataSet, un DataSource, un DBEdit, un DBGrid, todos ellos son objetos.

Si ya has trabajado con la triada mencionada, ¿qué ganas proveyendo los mismos objetos, como un DataSet, mediante un método? ¿Dónde está la independencia de la capa de datos si métodos como Leer reciben un componente tan específico como un TADOConnection?

Quizá, y recalco el quizá, una idea sencilla como ésta de Wayne Niddery, te pueda dar un punto de partida parra algo no tan complicado.

// Saludos
Responder Con Cita
  #6  
Antiguo 21-08-2012
Avatar de 2-D@monic
2-D@monic 2-D@monic is offline
Miembro
 
Registrado: may 2007
Posts: 94
Poder: 17
2-D@monic Va por buen camino
Ahora me toca a mí..... cómo resolviste este problema?
Sabes analizando el caso se puede hacer esto con clientdataset, llenándolo para que esté disponible "off-line" y devolverlo, el problema es el manejo de memoria, es por esto que sale el access violation, yo intenté hacerlo así estoy usando C++ builder y la verdad manejar punteros no es mi fuerte.....
Por temas de tiempo tampoco pude hacerlo de la manera que tendría que ser para disminuir el acople de objetos (gracias! enfoque OOP) y lo hice como todos lo hacemos, si quieres profundizar en este enfoque de tres capas tienes que utilizar DataSnap, tómate tu tiempo pero verás que valió la pena.
__________________
Soy pésimo en lo que mejor hago y por eso me siento bendecido.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Sql que no retorna datos me da error:invalid variant type conversion bezaig SQL 6 17-03-2010 08:58:53
Procedimiento que retorna XML mamaro Firebird e Interbase 3 05-03-2008 17:47:02
Capturar Valor que Retorna un SP subzero MS SQL Server 3 18-01-2008 21:38:37
Funcion de Que Retorna una Cadena Abel Garcia Firebird e Interbase 4 23-07-2005 10:30:02
Acceso a método d 1 form dsd Módulo d Datos Muten Varios 2 25-11-2003 13:50:57


La franja horaria es GMT +2. Ahora son las 08:25:04.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi