Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Ventana de Busqueda (https://www.clubdelphi.com/foros/showthread.php?t=78475)

escorpionrojo43 23-04-2012 17:22:50

Ventana de Busqueda
 
Hola Companeros
tengo el siguiente problema.

En mi aplicacion he puesto una opcion de busqueda de clientes, la opcion de busqueda funciona bien el problema es que me da error al pasa los datos a la ventana que lo llama.

Código Delphi [-]
procedure TFFactura.btnDatosClienteClick(Sender: TObject);
begin
    Application.CreateForm(TFBuscaPaciente, FBuscaPaciente);
      if FBuscaPaciente.ShowModal = mrOk then
      begin
        editclt_codigo.Text := FBuscaPaciente.uniquery1.FieldByName('IDPACIENTE').asString;
      end;
    FBuscaPaciente.Destroy
end;

al ejecutar esta parte del codigo me da un error
access violation at address 00525133

la ventana de busqueda la tengo con la propiedad visible false y el formstyle es fsnormal.
alguien me puede ayudar con esto?

MartinS 23-04-2012 17:30:27

Hola: Podrias poner el codigo que realiza la consulta?

Saludos

escorpionrojo43 23-04-2012 17:33:56

Cita:

Empezado por MartinS (Mensaje 430680)
Hola: Podrias poner el codigo que realiza la consulta?

Saludos

Este es el codigo del formulario buscador completo
Código Delphi [-]
unit UbuscaPaciente;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, StdCtrls, ExtCtrls, Grids, DBGrids, MemDS, DBAccess, Uni, Buttons;

type
  TFBuscaPaciente = class(TForm)
    UniQuery1: TUniQuery;
    DBGrid1: TDBGrid;
    Panel1: TPanel;
    Panel2: TPanel;
    Label18: TLabel;
    Edit1: TEdit;
    RadioGroup2: TRadioGroup;
    DataSource1: TDataSource;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    procedure query();
    procedure RadioGroup2Click(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure DBGrid1KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FBuscaPaciente: TFBuscaPaciente;

implementation

uses Udatamodulo;

{$R *.dfm}

procedure TFBuscaPaciente.DBGrid1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if key = vk_return then
    bitbtn2.SetFocus;
end;

procedure TFBuscaPaciente.Edit1Change(Sender: TObject);
begin
query
end;

procedure TFBuscaPaciente.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  freeandnil(FBuscaPaciente);
end;

procedure TFBuscaPaciente.query();
begin
  with UniQuery1, sql do
  begin
    close;
    clear;
    begin
      if RadioGroup2.ItemIndex = 0 then
        Add(' SELECT * FROM paciente where upper(nombre) like upper('+#39+'%'+edit1.text+'%'+#39+')')
      else
        Add(' SELECT * FROM paciente where upper(telefono) like upper('+#39+'%'+edit1.text+'%'+#39+')');
    end;
    open;
  end;
end;

procedure TFBuscaPaciente.RadioGroup2Click(Sender: TObject);
begin
query
end;

end.

ElDioni 23-04-2012 17:34:03

Hola,

parece que cuando quieres rescatar el dato estás accediendo a algo que ya no existe, ¿porqué no pruebas a enviar el dato desde el mismo formulario de busqueda en lugar de rescatarlo desde el principal?

Saludos.

Casimiro Noteví 23-04-2012 17:39:49

Este código es más peligroso que una caja de bombas :D

Código Delphi [-]
procedure TFBuscaPaciente.query(); 
begin   
  with UniQuery1, sql do   
  begin     
    close;     
    clear;    
    begin       
      if RadioGroup2.ItemIndex = 0 then         
        Add(' SELECT * FROM paciente where upper(nombre) like upper('+#39+'%'+edit1.text+'%'+#39+')')       
      else         
        Add(' SELECT * FROM paciente where upper(telefono) like upper('+#39+'%'+edit1.text+'%'+#39+')');     
    end;     
    open;   
  end; 
end;

escorpionrojo43 23-04-2012 17:42:36

Cita:

Empezado por ElDioni (Mensaje 430682)
Hola,

parece que cuando quieres rescatar el dato estás accediendo a algo que ya no existe, ¿porqué no pruebas a enviar el dato desde el mismo formulario de busqueda en lugar de rescatarlo desde el principal?

Saludos.

seria una buena solucion si solo ese formulario llamara la informacion pero quiero que otros formularios puedan hacer uso de la busqueda.
que crees que podria hacer en ese caso eldioni?

escorpionrojo43 23-04-2012 17:43:45

Cita:

Empezado por Casimiro Notevi (Mensaje 430683)
Este código es más peligroso que una caja de bombas :D

Código Delphi [-]
procedure TFBuscaPaciente.query(); 
begin   
  with UniQuery1, sql do   
  begin     
    close;     
    clear;    
    begin       
      if RadioGroup2.ItemIndex = 0 then         
        Add(' SELECT * FROM paciente where upper(nombre) like upper('+#39+'%'+edit1.text+'%'+#39+')')       
      else         
        Add(' SELECT * FROM paciente where upper(telefono) like upper('+#39+'%'+edit1.text+'%'+#39+')');     
    end;     
    open;   
  end; 
end;

Por que lo dices Casimiro?

Caro 23-04-2012 17:45:37

Hola, el error yo creo que te da por el OnClose de tu formulario de busqueda:

Código Delphi [-]
 //liberas tu formulario antes de tiempo
 //comenta esta linea y prueba
 freeandnil(FBuscaPaciente);

Saluditos

escorpionrojo43 23-04-2012 17:47:40

Cita:

Empezado por Caro (Mensaje 430686)
Hola, el error yo creo que te da por el OnClose de tu formulario de busqueda:

Código Delphi [-]
 //liberas tu formulario antes de tiempo
 //comenta esta linea y prueba
 freeandnil(FBuscaPaciente);

Saluditos

efectivamente ese era el problema
Gracias caro.

escorpionrojo43 23-04-2012 17:49:22

Casimiro
me ha causado una gran inquietud lo que dijiste podrias decirme lo peligroso del codigo por favor?

Caro 23-04-2012 17:49:34

Hola, ademas de lo que he comentado antes, despues haces un Destroy de tu formulario de busqueda que ya ha sido liberado.

Saluditos

Delphius 23-04-2012 18:02:23

Cita:

Empezado por Casimiro Notevi (Mensaje 430683)
Este código es más peligroso que una caja de bombas :D

Más peligroso que un mono con una ametralladora... una AK-47 para ser exacto :D


escorpionrojo43 23-04-2012 18:07:19

Cita:

Empezado por Delphius (Mensaje 430691)
Más peligroso que un mono con una ametralladora... una AK-47 para ser exacto :D


estimado Delphius
en vista de que nuestro companero aun no me dado respuesta y tu lo secundas en su comentario podrias decirme por favor que es lo peligroso de mi codigo para solucionarlo.
y de que manera lo podrias hacer tu?
gracias.

mightydragonlor 23-04-2012 18:07:47

Cita:

Empezado por escorpionrojo43 (Mensaje 430689)
Casimiro
me ha causado una gran inquietud lo que dijiste podrias decirme lo peligroso del codigo por favor?

No sé que esté pensando Casimiro, pero de algo si estoy seguro, 1 - SQL Injection, 2 - Bajo rendimiento, ya que cada vez que mandas a un motor una consulta SQL hace que el motor tenga un rendimiento mucho menor que si ejecutaras un procedimiento almacenado o vista.

Delphius 23-04-2012 18:09:58

Bueno, es peligroso en 1er lugar porque es muy prospenso a una injección de SQL. En este hilo se ha comentado al respecto.

Saludos,

Casimiro Noteví 23-04-2012 18:10:29

Es peligroso porque puedes estar haciendo algo que no sabes que lo estabas haciendo.
Aunque en este caso pueda parece bastante claro, nunca estás realmente seguro de que hace las cosas bien: que el open sea del query, que el close sea del sql ¿o era al revés?, que no haya un error con los begin end y esté llamando al close del formulario, etc.
Además que para hacer depuración de código no sirve.
Algunas veces se ha hablado de que existen empresas que tienen prohibido usar el with

roman 23-04-2012 18:19:57

Cita:

Empezado por mightydragonlor (Mensaje 430694)
2 - Bajo rendimiento, ya que cada vez que mandas a un motor una consulta SQL hace que el motor tenga un rendimiento mucho menor que si ejecutaras un procedimiento almacenado o vista.

A ver, esta parte no me queda clara. ¿Que los motores de bases de datos no están precisamente para mandarles consultas? En este caso -buscar pacientes- ¿cómo nos ayudaría un procedimiento almacenado?

// Saludos

escorpionrojo43 23-04-2012 18:21:54

ok necesito documentarme mas al respecto.
gracias por la observación. ahora bien ya ven como ejecuto yo esa consulta.
me podrian dar un buen ejemplo de como hacerlo. asi fue que me ensenaron y obviamente no me dijeron las consecuencias.

Puede alguien poner el codigo de forma correcta para fines didacticos?
gracias.

mightydragonlor 23-04-2012 18:46:40

Cita:

Empezado por roman (Mensaje 430698)
A ver, esta parte no me queda clara. ¿Que los motores de bases de datos no están precisamente para mandarles consultas? En este caso -buscar pacientes- ¿cómo nos ayudaría un procedimiento almacenado?

// Saludos

No es que no estén preparados, pero a un nivel mas técnico, cuando mandas un Select bla bla bla esta instrucción debe ser parseada, estudiada para conseguir un plan de ejecución óptimo y luego ejecutada, cuando creas un procedimiento almacenado o una vista, lo anterior solo se hace una vez, cuando se crea, el resto de las veces ya no tiene por que hacerlo, por que ya lo tiene definido, pero si se hace algún cambio en índices, cuando se ejecute nuevamente la vista o procedimiento almacenado, se vuelve a generar el plan de ejecución y se sigue usando siempre, excepto si vuelve a cambiar algún índice, pero cuando mandas un select directo a la base de datos, esto se hace siempre, imagina que tienes 1000 usuario simultaneos haciendo esto, cada minuto, la diferencia es salvaje, espero te haya ayudado en algo, el tema es bien complejo y muy extenso, pero traté de hacerlo de la mejor manera.

roman 23-04-2012 18:53:30

Gracias. Entonces, ¿lo recomendado es llenar la base de procedimientos almacenados e invocarlos desde la aplicación cliente?

// Saludos

mightydragonlor 23-04-2012 18:57:55

Cita:

Empezado por roman (Mensaje 430703)
Gracias. Entonces, ¿lo recomendado es llenar la base de procedimientos almacenados e invocarlos desde la aplicación cliente?

// Saludos

Actualmente es lo que hago, estoy haciendolo en Oracle, MS-SQL y Firebird, con muy buenos resultados, teniendo una ventaja adicional al rendimiento, cuando debo hacer un cambio en la lógica del procedimiento almacenado, sin cambiar parámetros de entrada y salida, no tengo que generar ningún cambio en el programa =)

Delphius 23-04-2012 19:16:45

Cita:

Empezado por roman (Mensaje 430703)
Gracias. Entonces, ¿lo recomendado es llenar la base de procedimientos almacenados e invocarlos desde la aplicación cliente?

// Saludos

No me atrevería a asegurar que todas las consultas se llevaran a un procedimiento almacenado y/o vistas en el lado servidor como para utilizar tan libre la palabra "llenar" pero... en lo posible yo diría que hay que dejarle al motor las cosas que sabe hacer bien.

Y justamente si tienes consultas estáticas, que no vas a cambiar nunca (*) en la aplicación y que se va a estar lanzando cada x segundos en varios puestos, es mejor dejarla ya preparada y servida en el servidor e invocar a las vistas y/o procedimientos almacenados.

(*) No al menos hasta que venga un cambio en los requisitos, restricciones y/o en el rediseño o proceso de reingeniería para la aplicación.

Esto lleva también otra ventaja extra: hace más seguro nuestro al sistema y reduce también los peligros de una injección de código (a menos claro que el usuario tenga plena libertad de mandar a hacer lo que se le ocurra).

Yo al menos soy creyente de disponer vistas. Me resulta mucho más claro.

Saludos,

mightydragonlor 23-04-2012 19:21:09

Lo que dice Delphius es muy cierto, hay caso en que los requisitos necesitan que hagas algo demasiado flexible y debas hacerlo en la aplicación y no tenga cabida en una vista o sp, hasta el momento no me he topado con ninguno, todo siempre lo mandamos a sps y vistas xD

Caminante 23-04-2012 19:21:29

Bueno lo que yo hago en esos casos es poner el codigo de busqueda en una funcion de clase (class function)

Código Delphi [-]
class function TfrmBusqueda.Buscar(DatoaBuscar:string;Var ID:integer):boolean;

En el parametro de salida retorno el codigo encontrado.
La llamada quedaria asi:

Código Delphi [-]
If TfrmBusqueda.Buscar(MIparametro,I) then
//Trabajar con el retorno (el parametro I)


Disculpa si no soy mas explicito pero es q de momento no tengo delphi a mano.

Espero te sirva

Saludos

PepeLolo 24-04-2012 23:50:49

En mi caso todas las consultas para explotación de información las almaceno en la BBDD. Así no hay que generar nuevas versiones de la aplicación. Si es necesario un SP para a consulta, se crea y es transparente para el usuario, en pocos minutos o en muchos.... Depende de la complejidad, el usuario dispone de una consulta que hará uso de (SQL, SP o Vistas) :D

PepeLolo 24-04-2012 23:55:53

Para evitar la inyección de SQL, uso parámetros para los valores, identificando el tipo de parámetro esperado previamente. Por cierto esto incrementa la velocidad de preparación de SQL.


La franja horaria es GMT +2. Ahora son las 10:13:12.

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