PDA

Ver la Versión Completa : Procedimientos en DataModule


leanfreue
16-04-2007, 23:42:49
Hola amigos, tengo el siguiente problema:

Quiero hacer un DataModule para utilizar como base para otros DataModule, espcíficamente para hacer Altas, Bajas y Modificaciones. Hay algunos procedimientos que son siempre los mismos, por lo que los puse dentro del DataModule y listo, pero esos procedimientos llaman a su vez a otros procedimientos que están dentro del mismo DM, a los cuales quiero poder ingresarles distintas líneas de código para cada caso. El problema que tengo es que cuando llamo al procedimiento principal y este quiere acceder a los otros subprocedimientos me da un error de Access Violation.

Se los muestro mejor con un ejemplo:

DataModulePrincipal (Este lo tengo en el ObjectRepository)

...
public
procedure AgregarDatos;
procedure ChequearUsuario;
procedure PonerProximoCodigo; virtual;
...

implementation

procedure AgregarDatos;
begin
self.ChequearUsuario;
self.PonerProximoCodigo; **** ACA DA ACCESS VIOLATION ****
end;

procedure ChequearUsuario;
...

procedure PonerProximoCodigo;
begin
// Acá no pongo nada, porque el código que ingrese depende
// del ABM que estoy haciendo, por ejemplo, buscar el próximo código
// de cliente, o de proveedor, o de artículo, etc.
end;



DataModuleClientes (Este es el que heredo de DataModulePrincipal)

...
public
procedure PonerProximoCodigo; override;
...

implementation

procedure PonerProximoCodigo;
begin
// Escribo el código necesario para buscar el próximo código de cliente.
end;



Desde un formulario que utiliza el DataModuleCliente, quiero llamar a DataModuleCliente.Agregar, pero me da error.
Noté que el error aparece cuando desde el DataModule se llama a un procedimiento que tiene Override.

Qué es lo que estoy haciendo mal?
Estoy muy lejos de lograr lo que busco?

Bueno, espero haber explicado bien mi inconveniente y les agradezco a todos por su tiempo.

Saludos, Leandro.

leanfreue
17-04-2007, 04:03:31
Hola otra vez, tal vez me expliqué mal sobre lo que quiero hacer.
Quiero llamar desde una clase a un método de un objeto.

Se puede?

Estuve leyendo (ian marteens, marco cantu, etc.) y todos hablan de un "procedure of object", pero por lo que ví se refiere al manejo de eventos, y la idea no es responder a un evento en particular.

Espero haberme explicado mejor y gracias otra vez.

Leandro.

Al González
17-04-2007, 08:45:49
¡Hola Leandro!

En términos generales creo que es entendible el propósito, mas el código que nos presentas pareciera estar algo incompleto en lugares esenciales. Tal vez ayudaría que expusieras una copia íntegra del código (si no es algo muy privado) o cuando menos que las líneas presentadas se hayan compilado sin problemas, para evitar errores de apreciación de nuestra parte.

Agradezco respuesta consecuente a este llamado.

Un abrazo recortado.

Al González. :)

AzidRain
17-04-2007, 16:20:14
Normalmente ese error surge cuando se quiere accesar a alguna propiedad o método de un objeto que no se ha creado todavía. Como dice Al, el código que nos pones no nos ayuda mucho. Revisa bien la creación de los objetos en tiempo de ejecución, lo mas probable es que no estes inicializando

leanfreue
18-04-2007, 01:36:09
Hola Al Gonzalez y AzidRain, gracias por la respuesta, acá les pongo el código completo...

Este es el módulo de datos que utilizo como punto de partida.

unit dmABM_u;

interface

uses
SysUtils, Classes, FMTBcd, DB, DBClient, Provider, SqlExpr;

type

TdmABM = class(TDataModule)
SQLDataSet1: TSQLDataSet;
SQLDataSet2: TSQLDataSet;
DataSetProvider1: TDataSetProvider;
ClientDataSet1: TClientDataSet;
DataSource1: TDataSource;
private
{ Private declarations }
public
{ Public declarations }
Accion: Integer;
function Agregar: Boolean;
function Modificar: Boolean;
function Borrar: Boolean;
function Aceptar: Boolean;
function Cancelar: Boolean;
function ChequearAccion: Boolean; virtual;
function _DatosIniciales: Boolean; virtual;
function _cds2cmp: Boolean; virtual;
end;

var
dmABM: TdmABM;

implementation

uses DMConnection_u;

{$R *.dfm}

function TdmABM.Agregar: Boolean;
begin
if self.ChequearAccion = false then
exception.Create('No tiene permiso para esa acción');

if self._DatosIniciales = false then
exception.Create('Error con los datos iniciales');

self.Accion := 1;
result := true;
end;

function TdmABM.Modificar: Boolean;
begin
if self.ChequearAccion = false then
exception.Create('No tiene permiso para esa acción');

if self._cds2cmp = false then
exception.Create('Error en cds2cmp');

self.Accion := 2;
result := true;
end;

function TdmABM.Borrar: Boolean;
begin
// texto
result := true;
end;

function TdmABM.Aceptar: Boolean;
begin
// texto
result := true;
end;

function TdmABM.Cancelar: Boolean;
begin
// texto
result := true;
end;

function TdmABM.ChequearAccion: Boolean;
begin
result := true;
end;

function TdmABM._DatosIniciales: Boolean;
begin
// Buscar el próximo código disponible.
result := true;

end;

function TdmABM._cds2cmp: Boolean;
begin
// Pasar los valores de cada campo del dataset a self.cmp
result := true;

end;

end.



Este es el formulario que utilizo como punto de partida

unit frmABM_u;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Gradient, ExtCtrls, _TEdit_u, Grids, DBGrids,
_TDBGrid_u, ToolWin, ActnMan, ActnCtrls, Buttons, ComCtrls, dmABM_u;

type
TfrmABM = class(TForm)
cntTitulo: TPanel;
Gradient1: TGradient;
lblTitulo: TLabel;
MenuLateral: TPanel;
Splitter1: TSplitter;
cntGrilla: TPanel;
SplitterG_DR: TSplitter;
cntDR: TPanel;
PanelGrilla: TPanel;
TGrilla1: _TDBGrid;
txtLocator: _TEdit;
cntDatos: TScrollBox;
GradientDatos: TGradient;
ControlBar1: TControlBar;
ToolBar1: TToolBar;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
b_GrillaDatos: TBitBtn;
BitBtn5: TBitBtn;
b_Agregar: TButton;
b_Modificar: TButton;
b_Borrar: TButton;
b_Confirmar: TButton;
b_Cancelar: TButton;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SplitterG_DRMoved(Sender: TObject);
procedure cntGrillaResize(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure b_GrillaDatosClick(Sender: TObject);
procedure b_AgregarClick(Sender: TObject);
procedure b_ModificarClick(Sender: TObject);
procedure b_BorrarClick(Sender: TObject);
procedure b_ConfirmarClick(Sender: TObject);
procedure b_CancelarClick(Sender: TObject);
private
DRHeight: Integer;
public
DM: TdmABM;
procedure Create2; virtual;
procedure MostrarGrilla;
procedure MostrarDatos;
procedure Agregar;
procedure Modificar;
procedure Borrar;
procedure Confirmar;
procedure Cancelar;
function _cmp2ctrl: Boolean; virtual;
end;

var
frmABM: TfrmABM;

implementation

{$R *.dfm}

procedure TfrmABM.Create2;
begin
// codigo
end;

procedure TfrmABM.MostrarGrilla;
begin
self.cntGrilla.Visible := true;
self.cntDatos.Visible := false;
self.b_GrillaDatos.Caption := 'Datos';
end;

procedure TfrmABM.MostrarDatos;
begin
self.cntGrilla.Visible := false;
self.cntDatos.Visible := true;
self.b_GrillaDatos.Caption := 'Grilla';
end;

procedure TfrmABM.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;

procedure TfrmABM.SplitterG_DRMoved(Sender: TObject);
begin
DRHeight := cntDR.Height;
end;

procedure TfrmABM.cntGrillaResize(Sender: TObject);
begin
self.PanelGrilla.Height := self.cntGrilla.Height - self.DRHeight;
end;

procedure TfrmABM.FormCreate(Sender: TObject);
begin
// Inicialización del entorno gráfico del formulario.
self.cntDatos.Align := alClient;
self.GradientDatos.Align := alClient;
self.cntGrilla.Align := alClient;
self.DRHeight := cntDR.Height;
self.cntDR.Align := alBottom;
self.SplitterG_DR.Align := alBottom;
self.PanelGrilla.Align := alClient;
self.MostrarGrilla;
self.Create2;
end;

procedure TfrmABM.BitBtn2Click(Sender: TObject);
begin
self.MenuLateral.Visible := not self.MenuLateral.Visible;
end;

procedure TfrmABM.b_GrillaDatosClick(Sender: TObject);
begin
if self.cntGrilla.Visible = true then
self.MostrarDatos
else
self.MostrarGrilla
;
end;

// =============================================================================
procedure TfrmABM.Agregar;
begin
if self.DM.Agregar = false then
exception.Create('No se puede agregar');

if self._cmp2ctrl = false then
exception.Create('No se pueden pasar los cmp a los controles');

self.MostrarDatos;

end;

// =============================================================================
procedure TfrmABM.Modificar;
begin
if self.DM.Modificar = false then
exception.Create('No se puede modificar');

if self._cmp2ctrl = false then
exception.Create('No se pueden pasar los cmp a los controles');

self.MostrarDatos;

end;

// =============================================================================
procedure TfrmABM.Borrar;
begin
// texto
end;

// =============================================================================
procedure TfrmABM.Confirmar;
begin
// texto
end;

// =============================================================================
procedure TfrmABM.Cancelar;
begin
// texto
end;

procedure TfrmABM.b_AgregarClick(Sender: TObject);
begin
self.Agregar;
end;

procedure TfrmABM.b_ModificarClick(Sender: TObject);
begin
self.Modificar;
end;

procedure TfrmABM.b_BorrarClick(Sender: TObject);
begin
self.Borrar;
end;

procedure TfrmABM.b_ConfirmarClick(Sender: TObject);
begin
self.Confirmar;
end;

procedure TfrmABM.b_CancelarClick(Sender: TObject);
begin
self.Cancelar;
end;

function TfrmABM._cmp2ctrl: Boolean;
begin
result := true;

end;

end.


Este es el Módulo de datos de clientes. (Heredado de mdABM)

unit dmClientes2_u;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, dmABM_u, FMTBcd, DB, DBClient, Provider, SqlExpr;

type
TdmClientes2 = class(TdmABM)
private
{ Private declarations }
public
// Campos de la tabla Clientes.
cmpIdCliente: Integer;
cmpCodCliente: Integer;
cmpNomCliente: String;
cmpApeCliente: String;
cmpEmpCliente: String;
cmpMosCliente: String;
function ChequearAccion: Boolean; override;
function _DatosIniciales: Boolean; override;
function _cds2cmp: Boolean; override;
end;

var
dmClientes2: TdmClientes2;

implementation

uses DMConnection_u;

{$R *.dfm}

{ TdmClientes2 }

function TdmClientes2.ChequearAccion;
begin
result := true;
end;

function TdmClientes2._cds2cmp: Boolean;
begin
self.cmpIdCliente := self.ClientDataSet1.FieldByName('idCliente').AsInteger;
self.cmpCodCliente := self.ClientDataSet1.FieldByName('CodCliente').AsInteger;
self.cmpNomCliente := self.ClientDataSet1.FieldByName('Nombre').AsString;
self.cmpApeCliente := self.ClientDataSet1.FieldByName('Apellido').AsString;
self.cmpEmpCliente := self.ClientDataSet1.FieldByName('Empresa').AsString;
self.cmpMosCliente := self.ClientDataSet1.FieldByName('Mostrar').AsString;
result := true;
end;

function TdmClientes2._DatosIniciales: Boolean;
begin
result := true;
end;

end.



Y este es el formulario de clientes, heredado de frmABM

unit frmClientes2_u;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, frmABM_u, StdCtrls, Gradient, ExtCtrls, _TEdit_u, Grids,
DBGrids, _TDBGrid_u, ToolWin, ActnMan, ActnCtrls, Buttons, ComCtrls,
dmClientes2_u;

type
TfrmClientes2 = class(TfrmABM)
txtCodigo: TEdit;
txtNombre: TEdit;
txtApellido: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
private
{ Private declarations }
public
{ Public declarations }
DM: TDMclientes2;
procedure Create2; override;
function _cmp2ctrl: Boolean; override;
end;

var
frmClientes2: TfrmClientes2;

implementation

{$R *.dfm}

procedure TfrmClientes2.create2;
begin
self.DM := TDMclientes2.Create(self);
self.DM.SQLDataSet1.Active := true;
self.DM.ClientDataSet1.Active := true;
self.TGrilla1.DataSource := self.DM.DataSource1;
end;

function TfrmClientes2._cmp2ctrl: Boolean;
begin
self.txtCodigo.Text := IntToStr(self.DM.cmpCodCliente);
self.txtNombre.Text := self.DM.cmpNomCliente;
self.txtApellido.Text := self.DM.cmpApeCliente;
result := true;
end;

end.


Bueno, como les contaba antes, el error "Access violation" aparece cuando llamo a "Modificar" o "Agregar" desde el formulario. El error aparece en el módulo de datos dmABM, cuando intenta llamar a "ChequearAccion" (es donde despues voy a ingresar código para saber si el usuario actual tiene el permiso necesario).
Les agradezco desde ya por su tiempo.

Saludos, Leandro