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)
-   -   como crear componentes ado en tiempo de ejecucion (https://www.clubdelphi.com/foros/showthread.php?t=68875)

richy08 12-07-2010 19:24:14

como crear componentes ado en tiempo de ejecucion
 
buenos dias compañeros alguien tiene conocimiento de si es posible crear tadoconnections y tadoquery en tiempo de ejecucion y como hacerlo gracias por cualquier comentario

Caral 12-07-2010 19:44:50

Hola
De poderse, se puede.
La pregunta:
Para que?
No tiene mucha lógica crear un componente (NO visible) y ademas tener que colocarle todas las conexiones necesarias para que haga algo.
Saludos

richy08 12-07-2010 19:49:45

Cita:

Empezado por Caral (Mensaje 370108)
Hola
De poderse, se puede.
La pregunta:
Para que?
No tiene mucha lógica crear un componente (NO visible) y ademas tener que colocarle todas las conexiones necesarias para que haga algo.
Saludos

hola caral gracias por la respuesta, bueno el meollo del asunto es que me veo en la necesidad de usar hilos, por lo que he leido y los expertos del foro me han orientado los querys no son thread safe, por lo cual con cada hilo que cree necesito crearle su propio modulo de conexion y sus propios querys para que hagan su trabajo sobre la bd segun parametros que le pase(es la percepcion y lo que he entendido si estoy en un error pueden especificarmelo) es por ello que necesito hacerlo de esta forma, aunque me queda la duda de que pasa con esos componenetes despues de que le hilo se destruya, tambien los componentes creados se van o necesito destruirlos yo mismo..

Caral 12-07-2010 19:59:12

Hola
Lo normal es que cuando se crea un componente se destruya posteriormente.
Ahora, la siguiente pregunta:
Donde crearas estos componentes?, en algun form?.
Saludos

richy08 12-07-2010 20:06:42

no los componentes los creare dentro de un tmd_gral, y la aplicacion que contendra estos componentes estara corriendo en el server solo esperando llamadas de un tcpclient para realizar las acciones.

Caral 12-07-2010 20:32:03

Hola
No se lo que es un tmd_gral.
Aqui tienes un ejemplo con access.
Saludos
PD: La direccion que se le da esta en el codigo, para que te funcione cambiala a donde tengas la bd.

richy08 12-07-2010 20:43:30

gracias caral le echare un vistazo:) saludos

richy08 12-07-2010 21:12:12

sabes intente hacer algo parecido pero en una funcion que cada ves que un hilo mande llamar se cree su nueva conexion y su query que alterara las tablas de mysql pero me marca el siguiente error yno hallo como hacer un cast para convertir la variable, alguna forma de hacerlo gracias


[Error] Interfaces.pas(79): Incompatible types: 'TZConnection' and 'String'
Código Delphi [-]
zConnection:= TzConnection.Create(self);
       zConnection.Name:=Myusername;
       zConnection.Catalog:='lookup';
       zConnection.Database:='cdr';
       zConnection.HostName:='192.168.11.2';
       zConnection.Password:='system';
       zConnection.Protocol:='mysql-5';
       zConnection.port:=3306;
       zConnection.Protocol:='mysql-5';
       zConnection.User:='sitisystem';
       zConnection.Connect;

       //crea el query
       zQuery      :=   TzQuery.Create(self);
       zQuery.Name :=   Myusername+'2';
       zQuery.Connection:=Myusername; // aqui marca el error
       zQuery.SQL.Add('update lookup set  allowcalls=:allowcalls, ldesc=:ldesc where code=:code ');

Caral 12-07-2010 21:24:18

Hola
Da la impresion de que no tendrian que ser String los datos, segun el error que marca.
Código Delphi [-]
   zConnect1:= TzConnection.Create(self);
   With zConnect1 do
   begin
   Parent:= ??????
   Name:= Myusername;
   Catalog:= lookup;
   Database:= cdr;
   HostName:= 192.168.11.2;
   Password:= system;
   Protocol:= mysql-5;
   port:= 3306;
   User:= sitisystem;
   Connect := True;
   end;
       //crea el query
    zQuery1 := TzQuery.Create(self);
    With zQuery1 do
    begin
    Parent:= ????????
    Name :=   Myusername+'2';
    Connection:= zConnect1;
    SQL.Text:= 'update lookup set  allowcalls=:allowcalls, ldesc=:ldesc where code=:code ';
    Params.........
    open;
    end;
saludos

Caral 12-07-2010 21:34:09

Hola
Tambien podria estar aqui el error:
Código Delphi [-]
zConnect1:= TzConnection.Create(self);
   With zConnect1 do
   begin
   Parent:= ??????
   Name:= Myusername;
   Catalog:= lookup;
   Database:= cdr;
   HostName:= 192.168.11.2;
   Password:= system;
   Protocol:= mysql-5;
   port:= 3306;
   User:= sitisystem;
   Connect := True;
   end;
       //crea el query
    zQuery1 := TzQuery.Create(self);
    With zQuery1 do
    begin
    Parent:= ????????
    Name :=   Myusername+2; // aqui
    Connection:= zConnect1;
    SQL.Text:= 'update lookup set  allowcalls=:allowcalls, ldesc=:ldesc where code=:code ';
    Params.........
    open;
    end;
Pasaste de ADO a ZEOS sin avisar jejeje.
Saludos

richy08 12-07-2010 21:42:16

Cita:

Empezado por Caral (Mensaje 370122)
Hola
Tambien podria estar aqui el error:
Código Delphi [-]zConnect1:= TzConnection.Create(self); With zConnect1 do begin Parent:= ?????? Name:= Myusername; Catalog:= lookup; Database:= cdr; HostName:= 192.168.11.2; Password:= system; Protocol:= mysql-5; port:= 3306; User:= sitisystem; Connect := True; end; //crea el query zQuery1 := TzQuery.Create(self); With zQuery1 do begin Parent:= ???????? Name := Myusername+2; // aqui Connection:= zConnect1; SQL.Text:= 'update lookup set allowcalls=:allowcalls, ldesc=:ldesc where code=:code '; Params......... open; end;

Pasaste de ADO a ZEOS sin avisar jejeje.
Saludos

si perdon seme paso comentarlo, en esta linea no tendria que referenciar el nombre del componente que sera el nombre que tenga la variableMyusername que realmente es el nombre de la maquina que hizo que se creara el hilo??, lo comento por que se crearan componentes como llamadas de creacion de hilos halla, y para seguir con lo de que cada hilo tenga sus conexiones por separado no ocasionara algun error?? mil gracias por tu tiempo

Código Delphi [-]
 Connection:= zConnect1;

Caral 12-07-2010 21:46:04

Hola
No se.
Recuerda que vas a necesitar UN SOLO ZConnection para todo.
Con solo que lo crees una vez bastara.
Los query o tables los tienes que conectar al componente Zconnection que creaste, de lo contrario no encontrara la BD.
En esto nunca he hecho nada no puedo guiarte muy bien que digamos, asi que no te fíes mucho.
Saludos

richy08 12-07-2010 22:01:13

gracias caral por tu ayuda me has alumbrado un poco mas el camino seguire testeandolo para asegurarme.

Neftali [Germán.Estévez] 13-07-2010 10:56:33

Cita:

Empezado por Caral (Mensaje 370129)
Recuerda que vas a necesitar UN SOLO ZConnection para todo.
Con solo que lo crees una vez bastara.

Eso suele ser lo normal, pero en el caso de Ricky08 (por lo que ha comentado en otros mensajes) es que está trabajando con threads, y lo normal en Threads es que haya que crear una conexión independiente en cada thread, supongo que por eso el "crear componentes por código" y "crear diferentes conexiones".

En este caso creo que sí está justificado utilizar diferentes zConnections.

richy08 13-07-2010 16:18:11

asi es neftali es por ello el de crearlos dinamicamente aunque no encuentro informacion de como hacerlo por mas que busco no encuentro una lectura o un ejemplo de como crearlas conexiones y los querys:( en tiempo de ejecucion el dia es largo asi es que manos al teclado espero hoy terminarlo o encontrar una nueva opcion de como hacerlo saludos.

Neftali [Germán.Estévez] 13-07-2010 16:34:21

Se crean como cualquier otro componente en ejecución. Busca sobre creación de componentes en ejecución en los foros y encontrarás bastantes temas con ejemplos de código.

Hay una forma sencilla de saber cómo rellenar las propiedades. Crea un componente en un formulario y rellena las propiedades (por ejemplo un Zconnection) de forma que funcione correctamente. Graba el formulario y revisa las propiedades que se han guardado en el DFM.

Por ejemplo, si creas un ADOQuery en diseño, en el DFM hay esto:

Código:

  object ADOQuery1: TADOQuery
    ConnectionString =
      'FILE NAME=C:\TEST.udl'
    CursorType = ctStatic
    Parameters = <>
    SQL.Strings = (
      'select * from TDeposito where OID=184367')
    Left = 32
    Top = 16
  end

Para crearlo por código utilizarías este:

Código Delphi [-]
    ADOQuery2 := TADOQuery.Create(nil);
    ADOQuery2.ConnectionString :=
      'FILE NAME=C:\TEST.udl';
    ADOQuery2.CursorType := ctStatic;
    ADOQuery2.SQL.Text := 'select * from TDeposito where OID=184367';

richy08 13-07-2010 16:41:32

gracias neftali por el ejemplo lo de crear componentes ya lo solucione con la ayuda de caral, es solo que no entiendo en el siguiente codigo segun yo le doy un nombre al query pero al querer referenciarlo por el nombre no compila, ademas que hice pruebas con querys fijos pero truenan al traslaparse peticiones hacia el server alguna idea de como puedo refeenciar los querys creados por su nombre y otra duda necesito crear variables para controlar un ciclo while y estoy en la misma situacion saludos

Código Delphi [-]
function TFrm_Interfaces.CreaAdo(Myusername, nombre, idext: string; acode : integer):boolean;
begin
       //crea el query   mssql   busca extensiones
       Query      :=   TAdoquery.Create(nil);
       with Query  do
       begin
         Name :=   Myusername+'1';
         Connection:= md_gral.Con_Gral;
         SQL.text:='select idext, DesTel from pbx_ext where acode=:acode ';
         parameters.ParamByName('acode').Value:=1;
       end;


       //crea el query   mysql
       zQuery      :=   TzQuery.Create(nil);
       with zQuery  do
       begin
         Name :=   Myusername+'2';
         Connection:= md_gral.Con_PBXLin;
         SQL.text:='update lookup set  allowcalls=:allowcalls, ldesc=:ldesc where code=:code ';
         {ParamByName('allowcalls').Value:=1;
         ParamByName('ldesc').Value:=nombre;
         ParamByName('code').Value:=idext;}
         Parent:= Frm_Interfaces;
       end;
end;

Neftali [Germán.Estévez] 13-07-2010 16:50:01

Cita:

Empezado por richy08 (Mensaje 370207)
...es solo que no entiendo en el siguiente codigo segun yo le doy un nombre al query pero al querer referenciarlo por el nombre no compila

¿Cómo haces la referencia? ¿Qué codigo estás utilizando?

Que estés creando el Query en ejecución no quiere decir que no esté como propiedad del Thread (por ejemplo), para que pueda consultarse desde fuera. El problema es que no se cual es la estructura completa de tu programa.

richy08 13-07-2010 17:11:15

a ok gracias este es el codigo del ejecutable que se encuentra en el server y mas abajo pongo el del cliente, esta linea es donde tengo el error Connection:= Myusername+'z'; //aqui marca el error no se como asignarle la conexion

//server
Código Delphi [-]
unit Interfaces;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdThreadMgr, IdThreadMgrDefault, IdBaseComponent,
  IdComponent, IdTCPServer, DB, ADODB, strutils, dateutils, ZConnection,
  ZAbstractRODataset, ZAbstractDataset, ZDataset;

type
  PClient   = ^TClient;
  TClient   = record  // Object holding data of client (see events)
  DNS         : String[20];            { Hostname }
  Connected,                           { Time of connect }
  LastAction  : TDateTime;             { Time of last transaction }
  Thread      : Pointer;               { Pointer to thread }
  end;
  
  TFrm_Interfaces = class(TForm)
    CBServerActive: TCheckBox;
    Server: TIdTCPServer;
    IdThreadMgrDefault1: TIdThreadMgrDefault;
    Protocol: TMemo;
    procedure CBServerActiveClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure ServerConnect(AThread: TIdPeerThread);
    procedure ServerDisconnect(AThread: TIdPeerThread);
    procedure ServerExecute(AThread: TIdPeerThread);
  private
    { Private declarations }
    function CreaAdo(Myusername, nombre, idext: string; acode: integer):boolean;
  public
    { Public declarations }

  end;

var
  Frm_Interfaces: TFrm_Interfaces;
  Clients         : TThreadList;     // Holds the data of all clients
  Query     : TAdoquery;
  zQuery    : TzQuery;
  zConnect1 : Tzconnection;
  i, seleccion :integer;
  
implementation

uses GlobalUnit, Prg_MDgral;

{$R *.dfm}

function TFrm_Interfaces.CreaAdo(Myusername, nombre, idext: string; acode : integer):boolean;
begin
       zConnect1:= TzConnection.Create(self);
       With zConnect1 do
       begin
        Parent:= Frm_Interfaces;
        Name:= Myusername+'z';
        Catalog:= 'lookup';
        Database:= 'cdr';
        HostName:= '192.168.11.2';
        Password:= 'system';
        Protocol:= 'mysql-5';
        port:= 3306;
        User:= 'sitisystem';
        Connect
       end;
               
       //crea el query   mssql   busca extensiones
       Query      :=   TAdoquery.Create(self);
       with Query  do
       begin
         Name :=   Myusername+'1';
         Connection:= md_gral.Con_Gral;
         SQL.text:='select idext, DesTel from pbx_ext where acode=:acode ';
         //parameters.ParamByName('acode').Value:=1;
         Parent:= Frm_Interfaces;
       end;

       //crea el query   mysql
       zQuery      :=   TzQuery.Create(self);
       with zQuery  do
       begin
         Name :=   Myusername+'2';
         Connection:= Myusername+'z';  //aqui marca el error no se como asignarle la conexion
         SQL.text:='update lookup set  allowcalls=:allowcalls, ldesc=:ldesc where code=:code ';
         {ParamByName('allowcalls').Value:=1;
         ParamByName('ldesc').Value:=nombre;
         ParamByName('code').Value:=idext;}
         Parent:= Frm_Interfaces;
       end;
end;

procedure TFrm_Interfaces.CBServerActiveClick(Sender: TObject);
begin
  Server.Active := CBServerActive.Checked;
end;



procedure TFrm_Interfaces.ServerConnect(AThread: TIdPeerThread);
var
  NewClient: PClient;
begin
GetMem(NewClient, SizeOf(TClient));

  NewClient.DNS         := AThread.Connection.LocalName;
  NewClient.Connected   := Now;
  NewClient.LastAction  := NewClient.Connected;
  NewClient.Thread      :=AThread;

  AThread.Data:=TObject(NewClient);

  try
    Clients.LockList.Add(NewClient);
  finally
    Clients.UnlockList;
  end;

  Protocol.Lines.Add(TimeToStr(Time)+' Connection from "'+NewClient.DNS+'"');
end;



procedure TFrm_Interfaces.ServerExecute(AThread: TIdPeerThread);
var
  ActClient, RecClient: PClient;                                                                              
  CommBlock, NewCommBlock: TCommBlock;
  RecThread: TIdPeerThread;
  i: Integer;
begin
  if not AThread.Terminated and AThread.Connection.Connected then
  begin
    AThread.Connection.ReadBuffer (CommBlock, SizeOf (CommBlock));
    ActClient := PClient(AThread.Data);
    ActClient.LastAction := Now;  // update the time of last action

    CreaAdo(CommBlock.MyUserName, CommBlock.nombre, CommBlock.idext, CommBlock.acode);

    Protocol.Lines.Add (TimeToStr(Time)+' !! "'+CommBlock.MyUserName);
    NewCommBlock.Command := 'DIALOG';       // the message should popup on the client's screen
    NewCommBlock.MyUserName := '[PBX Server]';  // the server's username
    NewCommBlock.Msg := 'The process was done  ';  // the message to show
    NewCommBlock.ReceiverName := '[return-to-sender]'; // unnecessary

    AThread.Connection.WriteBuffer (NewCommBlock, SizeOf (NewCommBlock), true);  // and there it goes...
  end;
end;

procedure TFrm_Interfaces.ServerDisconnect(AThread: TIdPeerThread);
var
 ActClient: PClient;
begin
  ActClient := PClient(AThread.Data);
  Protocol.Lines.Add (TimeToStr(Time)+' Disconnect from "'+ActClient^.DNS+'"');
  try
    Clients.LockList.Remove(ActClient);
  finally
    Clients.UnlockList;
  end;
  FreeMem(ActClient);
  AThread.Data := nil;
end;


procedure TFrm_Interfaces.FormCreate(Sender: TObject);
begin
  Clients := TThreadList.Create;
end;

procedure TFrm_Interfaces.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  Server.Active := False;
  Clients.Free;
end;

end.


y este es el fragmento del boton de una de las pantallas que lo mandara llamar.

//client
Código Delphi [-]
.
.
.
TClientHandleThread = class(TThread)
   private
     CB: TCommBlock;
     procedure HandleInput;
   protected
     procedure Execute; override;

  end;


var
  Frm_PosGue: TFrm_PosGue;
  ClientHandleThread: TClientHandleThread;   // variable (type see above)

.
.
.
.

procedure TClientHandleThread.HandleInput;
begin
  if CB.Command = 'MESSAGE' then
     Frm_Posgue.IncomingMessages.Lines.Add (CB.MyUserName + ': ' + CB.Msg)
  else
  if CB.Command = 'DIALOG' then
    MessageDlg ('"'+CB.MyUserName+'" sends you this message:'+#13+CB.Msg, mtInformation, [mbOk], 0)
  else  // unknown command
    MessageDlg('Unknown command "'+CB.Command+'" containing this message:'+#13+CB.Msg, mtError, [mbOk], 0);
end;

procedure TClientHandleThread.Execute;
begin
  while not Terminated do
  begin
    if not Frm_Posgue.Client.Connected then
      Terminate
    else
    try
      Frm_Posgue.Client.ReadBuffer(CB, SizeOf (CB));
      Synchronize(HandleInput);
    except
    end;
  end;
end;
.
.
.

procedure TFrm_PosGue.Btb_InhClick(Sender: TObject);
var
i, seleccion :integer;
CommBlock : TCommBlock;
begin
 CBClientActive.Checked:=true;
      if CBClientActive.Checked then
      begin
        try
           Client.Connect(10000);  // in Indy < 8.1 leave the parameter away
           ClientHandleThread := TClientHandleThread.Create(True); //crea el hilo
           ClientHandleThread.FreeOnTerminate:=True; //para que no se ejecute inmediatamente
           ClientHandleThread.Resume; //lo manda ejecutar
        except
            on E: Exception do MessageDlg ('Error while connecting:'+#13+E.Message, mtError, [mbOk], 0);
        end;
      end
      else
      begin
       ClientHandleThread.Terminate;
       Client.Disconnect;
      end;

    CommBlock.Command      := '';//EditCommand.Text;         // assign the data
    CommBlock.MyUserName   := Client.LocalName;
    CommBlock.Msg          := 'hola';//EditMessage.Text;
    CommBlock.ReceiverName := 'Desarrollo-lap';//EditRecipient.Text;
    CommBlock.nconf        := Qry_principal.fieldbyname('nconf').Value;

    Client.WriteBuffer (CommBlock, SizeOf (CommBlock), true);
end;

Neftali [Germán.Estévez] 13-07-2010 17:16:17

Supongo que si es del tipo normal, a la propiedad de conexión deberás asignarle la conexión que has creado más arriba:

Código Delphi [-]
Connection:= zConnect1;

¿De qué tipo es esa propiedad?


La franja horaria es GMT +2. Ahora son las 18:51:10.

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