Ver Mensaje Individual
  #5  
Antiguo 17-06-2015
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Reputación: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Necesitas agregar mas clases a tu dominio, clases encargadas de mapear objetos desde la base de datos a tu programa.

Yo suelo crear un DataModule con 1 componente conexion, y luego objetos publicos que se definen en otras units

un ejemplo de un DataModule:

Código Delphi [-]
unit Data.DataModule;

uses
  ...
  Data.Managers.Socios // --> unit en donde esta definida una clase que me permite guardar, leer, borrar, etc "Socios"!
  ...

    TDM = class(TDataModule)
        FDGUIxWaitCursor1: TFDGUIxWaitCursor;
        FDPhysFBDriverLink1: TFDPhysFBDriverLink;
        Connection: TFDConnection;
        procedure DataModuleCreate(Sender: TObject);
        procedure DataModuleDestroy(Sender: TObject);
        procedure ConnectionAfterConnect(Sender: TObject);
        procedure ConnectionBeforeConnect(Sender: TObject);
    private
        { Private declarations }
        procedure InitManagers;
        procedure FreeManagers;
    public
        { Public declarations }
        Socios: TSociosMgr;  --> Aca tenemos la instancia publica a la que hay que pedirle que opere con los socios
    end;

procedure TDM.ConnectionAfterConnect(Sender: TObject);
begin
    InitManagers;
end;

procedure TDM.DataModuleCreate(Sender: TObject);
begin
    Connection.Connected := True;
end;

procedure TDM.DataModuleDestroy(Sender: TObject);
begin
    FreeManagers;
end;


procedure TDM.FreeManagers;
begin
  if Assigned(Socios) then
    Socios.Free;
end;

procedure TDM.InitManagers;
begin
    Socios := TSociosMgr.Create(Connection); // --> Le pasamos la conexion para que pueda acceder la BD
end;

y un poco de la clase TSociosMgr..

Código Delphi [-]
    { Clase encargada de la comunicacion con la base de datos. Implementa operaciones CRUD }
    TSociosMgr = class(TBaseMgr)  --> TBaseMgr es una clase abstracta que define algunas cosas
    public
        constructor Create(Connection: TFDConnection);
        function Get(const Id: int64): TSocio; overload;
        function Get(const Apellido, Nombre: string): TSocio; overload;
        function Delete(const Id: int64): boolean;
        function Search(const FParams: TSocioParams): TSocioData; 
//--> TSocioParams es un tipo record que contiene los parametros de busqueda, 
// a partir de esto armo una sentencia SQL
        function GetAll: TSocioData;
// --> TSocioData es otra clase especial.. mas abajo la muestro.
// Basicamente ADAPTA el resultado de una consulta SQL a: TDataSet, TDataSource, 
'' TList, < T > (donde < T > en este caso particular es TSocio!)
    end;

Aca esta TSocioData

Código Delphi [-]
    { Contiene un TDataSet con el resltado de un query. Puede representar la informacion como TDataSet, TDataSource
      o TList }
    TSocioData= class(TBaseData) --> Otra clase abstracta mas 
    public
        function AsList: TSocioList; --> TObjectList< TSocio > con algunos agregados: Comparadores por ej
        function RowToObj< T >: TSocio;
// --> Soy muy original con los nombres lo se.
// RowToObj "transforma" una fila del query en un TSocio, de alli su nombre
    end;

TSocioData, al descender de TBaseData, tiene una variable de tipo TDataSet (privada)

Entonces se puede implementar algo como esto:

Código Delphi [-]
function TSocioData.AsList: TSocioList;
begin
   // le paso una funcion por parametro que le dice "como" hacer para adaptar una fila del dataset a un TSocio!
    Result := TSocioList(inherited AsList< TSocio >(RowToObj< TSocio >));
    // al invocar a inherited AsList, se ejecuta un metodo de TBaseData, el cual hace algo masomenos asi
   // while not(YourDataSet.Eof) do
   // begin
  //   Lista.Add(RowToObj< T >);
  //   Next;
 // end;
end;

function TSocioData.RowToObj< T >: TSocio;
begin
    Result := TSocio.Create;
    with YourDataSet do
    begin
        Result.Id := FieldByName('Id').AsLargeInt;
        Result.IdRubro := FieldByName('IdRubro').AsInteger;
        Result.Apellido := FieldByName('Apellido').AsString;
        Result.Nombre := FieldByName('Nombre').AsString;
        Result.Mail := FieldByName('Mail').AsString;
        Result.FechaNac := FieldByName('FechaNac').AsDateTime;
        Result.FechaAlta := FieldByName('FechaAlta').AsDateTime;
        Result.Sexo.FromInteger(FieldByName('Sexo').AsInteger);
        Result.Observaciones := FieldByName('Observaciones').AsString;
        Result.Imagen := TImageLoader.LoadFromField(FieldByName('Imagen'));
    end;
end;

Se que es tedioso y largo, y eso que solo puse "pedazos sueltos" porque meter todas las clases involucradas en un post es una locura. Pero masomenos te das una idea

La mejor forma que yo encontre de que los objetos puedan colaborar entre si, es esta: Tenes que tener las claves foraneas en tu objeto, y cuando necesitas mas informacion para trabajar, se la pedis a la clase encargada de la persistencia!

En tu caso:

Código Delphi [-]

implementation

uses
  Data.DataModule, // --> Para poder acceder al TProveedorMgr
  Entities.Proveedor; // --> Aca estaria definido TProveedor

procedure TProducto.MostrarNombreDeProveedor;
var
  AProveedor: TProveedor;
begin
  AProveedor := DataModule.Proveedores.Get(IdProveedor); // --> Clave foranea en tu objeto TProducto!
  try
    ShowMessage(AProveedor.Nombre);
    ...
  finally
    AProveedor.Free;
  end;
end;

Como ya te dijeron por arriba esto lleva TIEMPO, y cuesta digerirlo. Yo aun sigo aprendiendo, experimentando y mejorando, aun me falta muchisimo para dominarlo bien, pero es una forma de programar que realmente me apasiona

Definitivamente deberias pegarle una ojeada a la sesion del CodeRage7 de Malcom Groves, en donde muestra un ejemplo de implementacion MVVM en Delphi

http://www.malcolmgroves.com/blog/?p=1340


-----

OFFTOPIC: Por cierto, los a genericos hay que agregarles espacio o no salen en el post!

Última edición por AgustinOrtu fecha: 17-06-2015 a las 06:03:09. Razón: Para mejor visualizacion
Responder Con Cita