PDA

Ver la Versión Completa : Nueva instancia del datamodule


Cañones
02-09-2011, 20:11:59
Hola a todos.
Tengo un formulario que al crearlo este crea su propio datamodule. Hastá acá funciona, desde siempre que lo vengo usando así.

Así creo el formulario

begin
FHorarios:=TfrmHorariosDelPersonal.Create(self);
Fhorarios.ShowModal;
Fhorarios.Free;
end;


Así crea el datamodule el formulario

begin inherited;
// creo el módulo de datos
dm:=TdmHorarios.Create(self);
dm.cargarPuestos;
end;


Dentro del formulario necesito crear otro formulario que use algunos procedimientos del dm creado anteriormente, pero desde ese formulario no puedo acceder a los procedimientos porque el dm está creado en el formulario anterior.
Probé creando un dm2 igual el primer dm pero no funciona.

Así creo el segundo formulario

begin
inherited;
// edición de HORARIOS
FHorarioDetalle:=TfrmHorarioPersonalDetalle.Create(self);
if FHorarioDetalle.ShowModal = mrOK then
dm.grabarHorario;
dm.cancelar;
end;


Espero ser claro, cualquier sugerencia o corrección en mi teoría será bienvenida.
Gracias por el tiempo.

dec
02-09-2011, 20:20:06
Hola,

Tal como lo planteas... igual es menester que "publiques" el "DM". Es decir, que prepares una variable global, o una referencia pública en algún formulario, de manera que puedas acceder al mismo. Por supuesto, tendrás que añadir la unidad donde quieres usar el "DM". No sé si te servirá de ayuda o no, pero, como los milagros no existen, si quieres acceder a algo "que no puedes", tendrás que "hacer que se pueda", y, hasta donde yo llego, así a bote pronto, la cosa pasa por "publicar" aquello a lo que quieres acceder, tal como he dihco. No sé si me explico. ;)

Cañones
02-09-2011, 20:25:02
Dec, gracias por tu respuesta, pero no entendí que me quisiste decir.
Saludos.

dec
02-09-2011, 20:49:38
Hola,

Bueno. No te preocupes, hay veces que no me entiendo ni yo. :) Pero a ver cómo te explico, no ya la solución a tu problema, pero, lo que yo quería decir antes.

Supongamos que tenemos varias unidades,... por ejemplo:


// Nuestro formulario principal

unit UMainForm;

interface

uses
Forms;

type
TMainForm = class(TForm)
end;

var
MainForm: TMainForm;

implementation

{$R *.dfm}

end.



// Nuestro formulario secundario

unit USecondaryForm;

interface

uses
Forms;

type
TSecondaryForm = class(TForm)
end;

var
SecondaryForm: TSecondaryForm;

implementation

{$R *.dfm}

end.




// Nuestro módulo de datos

unit UMyDataModule;

interface

uses
SysUtils, Classes;

type
TMyDataModule = class(TDataModule)
end;

var
MyDataModule: TMyDataModule;

implementation

{$R *.dfm}

end.



Ahora vamos a utilizar el módulo de datos desde el formulario principal, tal como yo he entendido que tú lo haces:


// Nuestro formulario principal

unit UMainForm;

interface

uses
Forms;

type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
end;

var
MainForm: TMainForm;

implementation

{$R *.dfm}

uses
UMyDataModule;

procedure TMainForm.FormCreate(Sender: TObject);
var
module : TMyDataModule;
begin
module := TMyDataModule.Create( nil );
try
// Aquí trabajamos con el módulo de datos
finally
module.Free();
end;
end;

end.


Estamos usando el módulo de datos en nuestro formulario principal. Lo estamos haciendo "de forma privada", incluso utilizamos una variable local al método "FormCreate". Si desde el formulario secundario quisiéramos acceder al módulo de datos, podríamos hacer lo mismo, empero, igual no es lo que queremos, puesto que accederíamos a una instancia distinta del módulo de datos. Tal vez esto sea lo que queramos, pero, me parece que no es el caso.

Así pues, ¿qué podemos hacer? Podemos, simplemente, utilizar la variable global "MyDataModule". De esta manera podríamos trabajar tal que así en ambos formularios:


// Nuestro formulario principal

unit UMainForm;

interface

uses
Forms;

type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
end;

var
MainForm: TMainForm;

implementation

{$R *.dfm}

uses
UMyDataModule;

procedure TMainForm.FormCreate(Sender: TObject);
begin
if not Assigned( MyDataModule ) then
MyDataModule := TMyDataModule.Create( nil );

// Aquí trabajamos con el módulo de datos

end;

end.


De este modo estaríamos trabajando en ambos formularios con la misma instancia del módulo de datos. Da igual quien cree la instancia antes, puesto que no la crearemos dos veces. Y yo creo que con esto podría terminarse el asunto, según lo he entendido yo, vaya. Sin embargo, todavía le podemos dar una vuelta de tuerca más, aunque no sé si ganaríamos algo o no.

Lo que puede verse a continuación es que hemos añadido el módulo de datos como un miembro de nuestro formulario principal. Además, para dar acceso al módulo de datos desde otros sitios, como nuestro formulario secundario, hemos declarado una propiedad que permite el acceso a nuestro módulo de datos. Vamos, tal que así:


// Nuestro formulario principal

unit UMainForm;

interface

uses
Forms, UMyDataModule;

type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
FMyDataModule : TMyDataModule;
public
property MyDataModule : TMyDataModule read FMyDataModule;
end;

var
MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.FormCreate(Sender: TObject);
begin
FMyDataModule := TMyDataModule.Create( nil );
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FMyDataModule.Free();
end;

end.



// Nuestro formulario secundario

unit USecondaryForm;

interface

uses
Forms;

type
TSecondaryForm = class(TForm)
procedure FormCreate(Sender: TObject);
end;

var
SecondaryForm: TSecondaryForm;

implementation

{$R *.dfm}

uses
UMainForm;

procedure TSecondaryForm.FormCreate(Sender: TObject);
begin

// Aquí trabajamos con el módulo de datos
MainForm.MyDataModule...
end;

end.



En conclusión. Como digo una posible solución (si entendí bien la cuestión) pasa por hacer público, por hacer visible de alguna manera el módulo de datos que queremos compartir entre diferentes formularios, unidades, etc. No sé si ahora ha quedado un poco más claro, no ya la solución a tu problema, pero al menos lo que yo trataba de decir en mi primer mensaje. :)

Cañones
02-09-2011, 20:59:56
Muschisimas gracias Dec. Ahora si entendí.
En el formulario que crea el DM al DM lo declaro como variable global.

implementation

uses udmHorarios, untAMhorariosPersonalDetalle;

var
dm:TdmHorarios;

{$R *.dfm}



Pero en el segundo formulario que creo necesito crear otra variable del tipo TdmHorarios igual a la que ya está creada. No necesito acceder a un dataset que ya está cargados, quiero una nueva instancia y cargar nuevamente los dataset y ejecutar procedimientos de TdmHorarios.
Gracias por las respuesta con completa.
Saludos.

dec
02-09-2011, 21:22:00
Hola,

Bueno. Si ya sabes cómo usar el módulo de datos desde el formulario que crea el DM, no tienes sino hacer lo mismo en el formulario secundario. Ahora bien, fíjate que la variable que muestras no es del todo global, es decir, es global al formulario en que se encuentra, pero, para que otros formularios puedan acceder a la misma debes declarar la variable en la cláusula "interfaz", no en la cláusula "implementation" como haces.

Pero, parece ser que esto no es lo que quieres hacer tú. Sino que quieres utilizar una **nueva** instancia del módulo de datos en tu formulario secundario. Pues bien, ¡crea la nueva instancia en dicho formulario, de la misma forma en que lo haces en el primero! por eso comprendo que algo se me está escapando, puesto que, no puedo creer que no sepas crear la nueva instancia en el segundo formulario, cuando lo estás haciendo en el primero la mar de bien. :)

¿Qué me dices?

Cañones
02-09-2011, 21:45:42
Dec, probé creando el segundo formulario y esté creado un nuevo DM. Pero el segundo DM parece ser el mismo que el primero y no funciona bien.
Ahora lo que voy a hacer es diseñar un nuevo DM y crear el nuevo DM.
No uso variables globales para todo el sistema, solo para el form, por eso está así. Por lo menos me alegra saber que está bien la teoría que manejaba.
Gracias Dec!

dec
02-09-2011, 21:52:38
Hola,

Bueno, es que dos instancias de un mismo objeto se parecen mucho... ¡como que son iguales! Je je je. Pero eso te iba a decir: si es que lo que te encuentras es algún error, no dejes de comentarlo aquí, con el mensaje que te aparece y todo. De este modo se te podrá intentar echar una mano. :)

Cañones
02-09-2011, 21:59:50
No me da error, pero ciertos procedimientos disparan eventos del primer formulario y este ejecuta otros procedimientos. No se que decirte, eso es lo que me hace sospechar que es el mismo DM.
También me lleva a pensar que no está muy bien diseñado... pero es otro tema.
Muchas gracias. Si me decís que la teoría mas o menos está encaminada, el resto tiene solución.
Saludos!

dec
02-09-2011, 22:36:41
No me da error, pero ciertos procedimientos disparan eventos del primer formulario y este ejecuta otros procedimientos. No se que decirte, eso es lo que me hace sospechar que es el mismo DM.
También me lleva a pensar que no está muy bien diseñado... pero es otro tema.
Muchas gracias. Si me decís que la teoría mas o menos está encaminada, el resto tiene solución.
Saludos!

No te preocupes, que no te pasa a ti sólo. Pero tiene toda la pinta de ser algo así. Es decir, si el módulo de datos "hace cosas" que, de alguna manera, interfieren con lo que antes ha hecho, o con lo que se espera que haga si se hace desde un formulario u otro... toca darle vueltas para que la "lógica" cuadre. Pero, tú mismo lo has dicho: no obtienes ningún error, sino una especie de comportamiento no deseado. Tal vez es cuestión de que le des unas cuentas vueltas al asunto, pues. :)

roman
02-09-2011, 23:36:53
No entiendo del todo cuál es el problema, pero quizá, y sólo quizá, esto tenga algo que ver con lo que planteé aquí (http://clubdelphi.com/foros/showthread.php?t=24473).

// Saludos