PDA

Ver la Versión Completa : Acceder a un DataSet desde otra unidad


SMTZ
23-12-2005, 13:40:39
Con .NET no se puede acceder a un DataSet creado en un form desde otra unidad distinta a la que pertenece el componente (inlcuso si se modifica y se crea como público).

La solución que yo he visto a este problema es crear variables globales tipo system.data.dataset y llamar al método "create" en tiempo de ejecución para poder crear la estructura de la base de datos, sin embargo, esta solución no me convence mucho, pués los componentes visuales están para utilizarlos y evitar crear variables a mano.

En Delphi Win32, existe un contenedor llamado DataModule que sirve para almacenar los componentes de bases de datos en él y poder llamarlos desde cualquier unidad, pero en Delphi .NET no existe este concepto y se echa mucho a faltar. Tampoco he visto ningún componente que realice una función similar.

¿Alguien tiene la solución a este problema? Creo que debe ser posible utilizar los componentes visuales desde cualquier unidad pero, al menos yo, todavía no he dado en el clavo.

Mirando en el google he visto que este problema lo tiene mucha gente pero no he visto ninguna solución.

Gracias.

__hector
23-12-2005, 14:54:37
Que no se puede? Eso no debe ser cierto.

Que sea una debilidad de Delphi, es posible, pero no de .NET. Un dataset instanciado, como cualquier otro tipo de objeto, puede ser accedido de acuerdo a los modificadores de acceso con los que se le ha declarado. Ahora bien, tienes que tomar en cuenta que, de acuerdo a la metodologia que utilices, puedes o no ver el contenido del dataset. Digamos que existen distintas formas (casos explicados en C#, que es el lenguaje con el que mas me familiarizo):

- Un DataSet marcado como static, puede ser accedido utilizando la nomenclatura NombreClase.NombreDataSet. Al mismo tiempo, no puede ser llenado desde una instancia de la clase que lo contiene, sino que en la misma clase debe ser tratado como un objeto que pertenece a una clase, y no a la instancia de la misma. Ej:


public class TalClase
{
.....
public static DataSet MiDataSet = new DataSet();
}


- Utilizando el patron de diseño Singleton (mi recomendacion particular), puedes obtener, a traves de los distintos formularios de tu programa, una instancia unica y global de una clase en particular (formulario, o cualquier otra clase). Este es un breve caso de uso:


public class ClaseFormulario {

private static ClaseFormulario instance;
private DataSet miDataSet;

public static ClaseFormulario GetInstance()
{
if(instance == null)
{
instance = new ClaseFormulario();
instance.miDataSet = new DataSet();
}
return instance;
}
}


Ahi tenemos: una variable privada, estatica, que contendra la instancia de la clase formulario a traves del ciclo de vida del programa, y un metodo, GetInstance, que verificara si la instancia ha sido creada previamente, y en caso de que no, crea una nueva instancia de ese tipo.

Usando este patron de diseño, se garantiza la disponibilidad de una misma instancia del objeto.

Caso de uso:


public class FormularioConsumer
{
private ClaseFormulario formConDataSet;

public FormularioConsumer
{
if(formConDataSet == null)
formConDataSet = ClaseFormulario.GetInstance();
}
}


Recomendacion: separa tus objetos de datos de los formularios, asi como los metodos que actualizan estos datos, e incluso los calculos y reglas de negocio, tal como lo hacias con D7..<, de forma tal que puedas reutilizar el codigo ahi escrito desde cualquier otro proyecto, con cambios minimos, ademas de tener un diseño mas claro.

SMTZ
23-12-2005, 15:48:20
Muchas gracias por a información. Tengo que probar lo que dices. Yo lo hacía de otra manera que funciona con cualquier componente excepto con los de bases de datos:

Tenemos dos unidades. En la primera se define el dataset y en la segunda un datagrid que accede al dataset declarado en la primera unidad:



Unidad1
===========

type
TWinForm = class(System.Windows.Forms.Form)
{$REGION 'Designer Managed Code'}
strict private { Delphi lo declara como privado pero si lo modificamos y lo ponemos como public
desde la Unidad2
tampoco podemos acceder a los componentes de bases de datos y, por ejemplo,
este problema no ocurriría si quiseramos acceder a un label.
/// <summary>
/// Required designer variable.
/// </summary>
Components: System.ComponentModel.Container;
BdpConnection1: Borland.Data.Provider.BdpConnection;
bdpSelectCommand1: Borland.Data.Provider.BdpCommand;
bdpInsertCommand1: Borland.Data.Provider.BdpCommand;
bdpUpdateCommand1: Borland.Data.Provider.BdpCommand;
bdpDeleteCommand1: Borland.Data.Provider.BdpCommand;
BdpDataAdapter1: Borland.Data.Provider.BdpDataAdapter;
DataSet1: System.Data.DataSet;
DataTable1: System.Data.DataTable;
DataColumn1: System.Data.DataColumn;
DataColumn2: System.Data.DataColumn;
DataColumn3: System.Data.DataColumn;
DataColumn4: System.Data.DataColumn;
DataColumn5: System.Data.DataColumn;
DataColumn6: System.Data.DataColumn;
DataColumn7: System.Data.DataColumn;
DataColumn8: System.Data.DataColumn;
DataColumn9: System.Data.DataColumn;
DataColumn10: System.Data.DataColumn;
DataColumn11: System.Data.DataColumn;
DataColumn12: System.Data.DataColumn;
DataColumn13: System.Data.DataColumn;
DataGrid1: System.Windows.Forms.DataGrid;
Button1: System.Windows.Forms.Button;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure InitializeComponent;
procedure Button1_Click(sender: System.Object; e: System.EventArgs);
{$ENDREGION}
strict protected
/// <summary>
/// Clean up any resources being used.
/// </summary>
procedure Dispose(Disposing: Boolean); override;
private
{ Private Declarations }
public
constructor Create;
end;

[assembly: RuntimeRequiredAttribute(TypeOf(TWinForm))]

implementation

uses WinForm1;

{$AUTOBOX ON}

{$REGION 'Windows Form Designer generated code'}
/// <summary>
/// Required method for Designer support -- do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure TWinForm.InitializeComponent;
type
TArrayOfSystem_Data_DataTable = array of System.Data.DataTable;
TArrayOfSystem_Data_DataColumn = array of System.Data.DataColumn;
begin
Self.BdpConnection1 := Borland.Data.Provider.BdpConnection.Create;
Self.bdpSelectCommand1 := Borland.Data.Provider.BdpCommand.Create;
Self.bdpInsertCommand1 := Borland.Data.Provider.BdpCommand.Create;
Self.bdpUpdateCommand1 := Borland.Data.Provider.BdpCommand.Create;
Self.bdpDeleteCommand1 := Borland.Data.Provider.BdpCommand.Create;
Self.BdpDataAdapter1 := Borland.Data.Provider.BdpDataAdapter.Create;
Self.DataSet1 := System.Data.DataSet.Create;
Self.DataTable1 := System.Data.DataTable.Create;
Self.DataColumn1 := System.Data.DataColumn.Create;
Self.DataColumn2 := System.Data.DataColumn.Create;
Self.DataColumn3 := System.Data.DataColumn.Create;
Self.DataColumn4 := System.Data.DataColumn.Create;
Self.DataColumn5 := System.Data.DataColumn.Create;
Self.DataColumn6 := System.Data.DataColumn.Create;
Self.DataColumn7 := System.Data.DataColumn.Create;
Self.DataColumn8 := System.Data.DataColumn.Create;
Self.DataColumn9 := System.Data.DataColumn.Create;
Self.DataColumn10 := System.Data.DataColumn.Create;
Self.DataColumn11 := System.Data.DataColumn.Create;
Self.DataColumn12 := System.Data.DataColumn.Create;
Self.DataColumn13 := System.Data.DataColumn.Create;
Self.DataGrid1 := System.Windows.Forms.DataGrid.Create;
Self.Button1 := System.Windows.Forms.Button.Create;
(System.ComponentModel.ISupportInitialize(Self.BdpDataAdapter1)).BeginInit;
(System.ComponentModel.ISupportInitialize(Self.DataSet1)).BeginInit;
(System.ComponentModel.ISupportInitialize(Self.DataTable1)).BeginInit;
(System.ComponentModel.ISupportInitialize(Self.DataGrid1)).BeginInit;
Self.SuspendLayout;
//
// BdpConnection1
//
Self.BdpConnection1.ConnectionOptions := 'transaction isolation=ReadCommit' +
'ted;decimalseparator=.';
Self.BdpConnection1.ConnectionString := 'assembly=Borland.Data.Oracle, Ver' +
'sion=2.5.0.0, Culture=neutral, PublicKeyToken=91d62ebb5b0d1b1b;vendorclie' +
'nt=oci.dll;pooling=True;grow on demand=True;database=ECODOMEs;username=sy' +
'stem;max pool size=100;password=cz4lg3;provider=Oracle;min pool size=0';
//
// bdpSelectCommand1
//
Self.bdpSelectCommand1.CommandOptions := nil;
Self.bdpSelectCommand1.CommandText := 'select * from usuarios';
Self.bdpSelectCommand1.CommandType := System.Data.CommandType.Text;
Self.bdpSelectCommand1.Connection := Self.BdpConnection1;
Self.bdpSelectCommand1.ParameterCount := (SmallInt(0));
Self.bdpSelectCommand1.SchemaName := nil;
Self.bdpSelectCommand1.Transaction := nil;
Self.bdpSelectCommand1.UpdatedRowSource := System.Data.UpdateRowSource.None;
//
// bdpInsertCommand1
//
Self.bdpInsertCommand1.CommandOptions := nil;
Self.bdpInsertCommand1.CommandText := nil;
Self.bdpInsertCommand1.CommandType := System.Data.CommandType.Text;
Self.bdpInsertCommand1.Connection := nil;
Self.bdpInsertCommand1.ParameterCount := (SmallInt(0));
Self.bdpInsertCommand1.SchemaName := nil;
Self.bdpInsertCommand1.Transaction := nil;
Self.bdpInsertCommand1.UpdatedRowSource := System.Data.UpdateRowSource.None;
//
// bdpUpdateCommand1
//
Self.bdpUpdateCommand1.CommandOptions := nil;
Self.bdpUpdateCommand1.CommandText := nil;
Self.bdpUpdateCommand1.CommandType := System.Data.CommandType.Text;
Self.bdpUpdateCommand1.Connection := nil;
Self.bdpUpdateCommand1.ParameterCount := (SmallInt(0));
Self.bdpUpdateCommand1.SchemaName := nil;
Self.bdpUpdateCommand1.Transaction := nil;
Self.bdpUpdateCommand1.UpdatedRowSource := System.Data.UpdateRowSource.None;
//
// bdpDeleteCommand1
//
Self.bdpDeleteCommand1.CommandOptions := nil;
Self.bdpDeleteCommand1.CommandText := nil;
Self.bdpDeleteCommand1.CommandType := System.Data.CommandType.Text;
Self.bdpDeleteCommand1.Connection := nil;
Self.bdpDeleteCommand1.ParameterCount := (SmallInt(0));
Self.bdpDeleteCommand1.SchemaName := nil;
Self.bdpDeleteCommand1.Transaction := nil;
Self.bdpDeleteCommand1.UpdatedRowSource := System.Data.UpdateRowSource.None;
//
// BdpDataAdapter1
//
Self.BdpDataAdapter1.Active := True;
Self.BdpDataAdapter1.DataSet := Self.DataSet1;
Self.BdpDataAdapter1.DataTable := Self.DataTable1;
Self.BdpDataAdapter1.DeleteCommand := Self.bdpDeleteCommand1;
Self.BdpDataAdapter1.InsertCommand := Self.bdpInsertCommand1;
Self.BdpDataAdapter1.SelectCommand := Self.bdpSelectCommand1;
Self.BdpDataAdapter1.StartRecord := 0;
Self.BdpDataAdapter1.UpdateCommand := Self.bdpUpdateCommand1;
//
// DataSet1
//
Self.DataSet1.DataSetName := 'NewDataSet';
Self.DataSet1.Locale := System.Globalization.CultureInfo.Create('es-ES');
Self.DataSet1.Tables.AddRange(TArrayOfSystem_Data_DataTable.Create(Self.DataTable1));
//
// DataTable1
//
Self.DataTable1.Columns.AddRange(TArrayOfSystem_Data_DataColumn.Create(Self.DataColumn1,
Self.DataColumn2, Self.DataColumn3, Self.DataColumn4, Self.DataColumn5,
Self.DataColumn6, Self.DataColumn7, Self.DataColumn8, Self.DataColumn9,
Self.DataColumn10, Self.DataColumn11, Self.DataColumn12, Self.DataColumn13));
Self.DataTable1.TableName := 'usuarios';
//
// DataColumn1
//
Self.DataColumn1.ColumnName := 'IDUSUARIO';
//
// DataColumn2
//
Self.DataColumn2.ColumnName := 'PASSWORD';
//
// DataColumn3
//
Self.DataColumn3.ColumnName := 'NOMBRE';
//
// DataColumn4
//
Self.DataColumn4.ColumnName := 'PRIMERAPELLIDO';
//
// DataColumn5
//
Self.DataColumn5.ColumnName := 'SEGUNDOAPELLIDO';
//
// DataColumn6
//
Self.DataColumn6.ColumnName := 'EMAIL';
//
// DataColumn7
//
Self.DataColumn7.ColumnName := 'ULTIMAOPERACIONREALIZADA';
Self.DataColumn7.DataType := TypeOf(System.DateTime);
//
// DataColumn8
//
Self.DataColumn8.ColumnName := 'USUARIOBLOQUEADO';
//
// DataColumn9
//
Self.DataColumn9.ColumnName := 'PRIVILEGIOS';
//
// DataColumn10
//
Self.DataColumn10.ColumnName := 'INTENTOSLOGIN';
Self.DataColumn10.DataType := TypeOf(System.Decimal);
//
// DataColumn11
//
Self.DataColumn11.ColumnName := 'CREADOPOR';
//
// DataColumn12
//
Self.DataColumn12.ColumnName := 'FECHACREACION';
Self.DataColumn12.DataType := TypeOf(System.DateTime);
//
// DataColumn13
//
Self.DataColumn13.ColumnName := 'FECHABLOQUEO';
Self.DataColumn13.DataType := TypeOf(System.DateTime);
//
// DataGrid1
//
Self.DataGrid1.DataMember := '';
Self.DataGrid1.DataSource := Self.DataTable1;
Self.DataGrid1.HeaderForeColor := System.Drawing.SystemColors.ControlText;
Self.DataGrid1.Location := System.Drawing.Point.Create(16, 24);
Self.DataGrid1.Name := 'DataGrid1';
Self.DataGrid1.Size := System.Drawing.Size.Create(304, 192);
Self.DataGrid1.TabIndex := 0;
//
// Button1
//
Self.Button1.Location := System.Drawing.Point.Create(168, 256);
Self.Button1.Name := 'Button1';
Self.Button1.TabIndex := 1;
Self.Button1.Text := 'Button1';
Include(Self.Button1.Click, Self.Button1_Click);
//
// TWinForm
//
Self.AutoScaleBaseSize := System.Drawing.Size.Create(5, 13);
Self.ClientSize := System.Drawing.Size.Create(376, 326);
Self.Controls.Add(Self.Button1);
Self.Controls.Add(Self.DataGrid1);
Self.Name := 'TWinForm';
Self.Text := 'WinForm';
(System.ComponentModel.ISupportInitialize(Self.BdpDataAdapter1)).EndInit;
(System.ComponentModel.ISupportInitialize(Self.DataSet1)).EndInit;
(System.ComponentModel.ISupportInitialize(Self.DataTable1)).EndInit;
(System.ComponentModel.ISupportInitialize(Self.DataGrid1)).EndInit;
Self.ResumeLayout(False);
end;
{$ENDREGION}

procedure TWinForm.Dispose(Disposing: Boolean);
begin
if Disposing then
begin
if Components <> nil then
Components.Dispose();
end;
inherited Dispose(Disposing);
end;

constructor TWinForm.Create;
begin
inherited Create;
//
// Required for Windows Form Designer support
//
InitializeComponent;
//
// TODO: Add any constructor code after InitializeComponent call
//
end;


Unidad2
=======


...

procedure TWinForm1.TWinForm1_Load(sender: System.Object; e: System.EventArgs);
begin

DataGrid1.DataSource := Unidad1.TWinForm.DataSet1; Esta línea no complica porque no encuentra declarado el DataSet1.

end;


...




Mañana o esta noche probaré lo que me explicas.


Saludos.

Lepe
23-12-2005, 16:25:26
Yo diría que es un simple "uses" el que falta:



Unit Unidad2;

uses Unidad1;
...


Aparte de lo ya explicado. Delphi permite ver las propiedades private, siempre y cuando 2 clases esten en la misma Unidad (archivo .pas).

Si estan en diferentes archivos .pas, tendrás que ponerlo en la parte public o published según desees.

saludos.

SMTZ
23-12-2005, 22:10:40
jeje, gracias por la info, pero eso son conocimientos básicos de delphi (pero es que en el .net todavía no estoy muy metido).

Un saludo.

SMTZ
24-12-2005, 09:01:47
Muchas gracias a todos por la ayuda. Finalmente, he descubierto que delphi .net es un poco particular a la hora de llamar a algunas funciones. Me explico:

Si tienes una clase definida tal que así:



Unidad1
=========

Type
MiForm = Class(System.Windows.Forms.Form)
Public
...
MiDataSet : System.Data.DataSet
...
End;


Desde otra unidad llamada Unidad2, lo lógico sería llamar al dataset de la siguiente manera:



uses
Unidad1;

...

Function Mi Funcion : Resultado;
Var
OtroDataSet : System.Data.DataSet;
Begin

OtroDataSet := MiForm.MiDataSet;

End;



en Delphi, ESTO ES UN ERROR, la manera correcta de llamar al DataSet de la unidad1 sería:



OtroDataSet := MiForm.Create.MiDataSet;



Por cierto, he estado haciendo pruebas con el diseño Singleton y resulta muy útil para muchas cosas.


Saludos.