Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Pasar un componente TDataBase a otra aplicacion en delphi (https://www.clubdelphi.com/foros/showthread.php?t=82410)

Eduardo Mendoza 05-03-2013 01:41:33

Pasar un componente TDataBase a otra aplicacion en delphi
 
Hola gente espero que alguien me pueda ayudar con algun tip, tengo una aplicacion en Delphi 2007 donde me conecto a una base de datos (Oracle) esta aplicacion toma algunas desiciones y dependiendo de esto ejecuta otro programa que utiliza la misma conexión, sin embargo no quiero abrir mas sesiones a la base de datos por efecto de eficientar los recursos. Conocen alguna manera sencilla de pasarle este componente ya instanciado a esta segunda aplicación?

ecfisa 05-03-2013 08:49:53

Hola Eduardo y bienvenido a Club Delphi :)

Como a todos los que se inician te invitamos a que leas nuestra guía de estilo.

Cita:

Conocen alguna manera sencilla de pasarle este componente ya instanciado a esta segunda aplicación?
Hasta donde sé no veo manera de enviar a otra aplicación una instancia en sí misma, ya que esta carecería de espacio o validez fuera del entorno de la primera. En cambio si es posible enviar los datos de dicha instancia u objeto.

Un modo sencillo que se me ocurre es guardar el componente desde la aplicación emisora y luego leerlo desde el componente de la aplicación receptora.

Aplicación emisora:
Código Delphi [-]
procedure SaveComponentToFile(aComponent: Tcomponent; aFileName: TFilename);
begin
  with TFileStream.Create(aFileName, fmCreate) do
  try
    WriteComponent(aComponent)
  finally
    Free
  end;
end;

Aplicación receptora:
Código Delphi [-]
procedure ReadComponentFromFile(aComponent: TComponent; aFileName: TFilename);
begin
 with TFileStream.Create(aFileName, fmOpenRead) do
  try
    ReadComponent(aComponent)
  finally
    Free;
  end;
  DeleteFile(aFileName); // (si deseas eliminarla)
end;
Pero no se evita el uso de otra instancia de la misma clase en la segunda aplicación.

Saludos. :)

cloayza 05-03-2013 22:18:43

Cita:

Empezado por Eduardo Mendoza (Mensaje 455996)
Hola gente espero que alguien me pueda ayudar con algun tip, tengo una aplicacion en Delphi 2007 donde me conecto a una base de datos (Oracle) esta aplicacion toma algunas desiciones y dependiendo de esto ejecuta otro programa que utiliza la misma conexión, sin embargo no quiero abrir mas sesiones a la base de datos por efecto de eficientar los recursos. Conocen alguna manera sencilla de pasarle este componente ya instanciado a esta segunda aplicación?

Creo que compartir la conexión entre aplicaciones no se podría, Pero entre una Aplicación y una DLL si se puede...
Esto va a depender de si tú segunda aplicación la puedes convertir en una DLL.

La idea es que la función que llames desde la DLL tiene que recibir el puntero a la conexión de la base de datos...

Código Delphi [-]
{-----------------------------------------------------------------------}
{                          START DLL CODE                               }
{-----------------------------------------------------------------------}

library testdll;

uses
   bde, db, dbtables, dialogs;

procedure myDLLCall(dbHandle : hdbidb); stdcall;
var
   Database : TDatabase;
   Query  : TQuery;
begin
   Database := TDatabase.Create(nil);
   try
      Database.DatabaseName := 'Brad';  {Some New DBName ie Alias}
      Database.Handle := dbHandle;
      Query := TQuery.Create(nil);
      try
         Query.DatabaseName := Database.DatabaseName;
         Query.Close;
         Query.SQL.Clear;
         Query.SQL.Add('SELECT SYSDATE FROM DUAL');
         Query.Open;
         ShowMessage(Query.FieldByName('SYSDATE').AsString);
      finally
         Query.Free;
      end;
   finally
      Database.Free;
   end;

exports
   myDllCall;

begin
end.


{-----------------------------------------------------------------------}
{                            START APP CODE                             }
{-----------------------------------------------------------------------}
unit appl;

uses
   Windows, Messges, SysUtils, Classes, Graphics, Contrils,
   Forms, Dialogs, StdCtrls, DB, BDE;

type
   TForm1 = class(TForm)
       dbOracle : TDatabase;
       Button1 : TButton;
       procedure Button1Click(Sender : TObject);
   end;

var
   Form1 : TForm;

procedure myDllCall(dbHandle : hdbidb); stdcall; external 'TESTDLL.DLL'

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender : TObject);
begin
   dbOracle.Open;
   myDllCall(dbOracle.Handle);
end;

Buscando entre mis cachureos encontre este código...Nunca lo he usado...
Espero te ayuda...

Yo lo realizo con componentes IBX y FIBPLus atacando Firebird....

Saludos cordiales

ecfisa 06-03-2013 00:41:19

Hola Eduardo.

Sobre tu consulta (usando COPYDATASTRUCT), tratándose de un TComponent, lamentablemente creo nos deja en una situación similar a la anterior por los motivos explicados.

Pero, aunque de forma mas compleja que con TFileStream, se pueden pasar los datos de la instancia, un ejemplo:

Aplicación emisora:
Código Delphi [-]
...
type
  TfrmEmisor = class(TForm)
    Button1: TButton;
    Database1: TDatabase;
    procedure Button1Click(Sender: TObject);
  private
  public
  end;

var
  frmEmisor: TfrmEmisor;

implementation

type
  TDBRegister = packed record
    AliasName    : string[255];
    Connected    : Boolean;
    DatabaseName : string[255];
    DriverName   : string[255];
    Exclusive    : Boolean;
    //...
  end;

procedure TfrmEmisor.Button1Click(Sender: TObject);
var
  CDS : COPYDATASTRUCT;
  H   : HWND;
  R   : TDBRegister;
begin
  with Database1 do
  begin
    R.AliasName      := AliasName;
    R.Connected      := Connected;
    R.DatabaseName   := DatabaseName;
    R.DriverName     := DriverName;
    R.Exclusive      := Exclusive;
   //...
  end;
  H := FindWindow(PChar('TfrmRecept'),PChar('TITULO'));
  try
    CDS.dwData := 0;
    CDS.cbData := SizeOf(R);
    CDS.lpData := @R;
    SendMessage(H, WM_COPYDATA, Integer(Handle), Integer(@CDS));
  finally
    CloseHandle(H);
  end;
end;
end.

Aplicación receptora:
Código Delphi [-]
...
type
  TfrmRecept = class(TForm)
    Database1: TDatabase;
    Memo1: TMemo;
  private
    procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
  public
  end;

var
  frmRecept: TfrmRecept;

implementation

type
  TDBRegister = packed record
    AliasName    : string[255];
    Connected    : Boolean;
    DatabaseName : string[255];
    DriverName   : string[255];
    Exclusive    : Boolean;
    // ...
  end;

procedure TfrmRecept.WMCopyData(var Msg: TWMCopyData);
const
   BOOLVALUE : array[Boolean] of string = ('False','True');
begin
  with TDBRegister(Msg.CopyDataStruct.lpData^) do
  begin
    Database1.AliasName      := AliasName;
    Database1.Connected      := Connected;
    Database1.DatabaseName   := DatabaseName;
    Database1.DriverName     := DriverName;
    Database1.Exclusive      := Exclusive;
    //...
  end;
  with Memo1 do
  begin
    Clear;
    Lines.Add('AliasName   : '+ Database1.AliasName);
    Lines.Add('Connected   : '+ BOOLVALUE[Database1.Connected]);
    Lines.Add('DatabaseName: '+ Database1.DatabaseName);
    Lines.Add('DriverName  : '+ Database1.DriverName);
    Lines.Add('Exclusive   : '+ BOOLVALUE[Database1.Exclusive]);
    //...
  end;
end;
end.
También tomá en cuenta implementar la opción que te sugiere cloayza.

Saludos.


La franja horaria es GMT +2. Ahora son las 06:03:48.

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