2008-11-08 60 views
17

Según this page, es posible usar TClientDataset como un conjunto de datos en memoria, completamente independiente de las bases de datos o archivos reales. Describe cómo configurar la estructura de la tabla del conjunto de datos y cómo cargar datos en ella en tiempo de ejecución. Pero cuando traté de seguir sus instrucciones en D2009, el paso 4 (table.Open) generó una excepción. Dijo que no tenía un proveedor especificado.Delphi: utilizando TClientDataset como un conjunto de datos en memoria

El punto entero del ejemplo en esa página es construir un conjunto de datos que no necesita un proveedor. ¿La página está equivocada, está desactualizada o me falta un paso en algún lugar? Y si la página es incorrecta, ¿qué necesito usar en su lugar para crear un conjunto de datos en memoria completamente independiente? He estado usando TJvMemoryData, pero si es posible me gustaría reducir la cantidad de dependencias adicionales que mi conjunto de datos agrega a mi proyecto.

Respuesta

20

en tiempo de ejecución puede utilizar table.CreateDataset o si se trata de una superficie de diseño puede hacer clic derecho en los CDS y haga clic en Crear conjunto de datos. necesita tener columnas/tipos especificados para el CDS antes de que pueda hacer esto.

+0

Haga clic en "crear conjunto de datos"? No hay tal opción cuando hago clic derecho en un TClientDataset en XE2. –

+1

Existe en XE7; quinta opción desde la parte superior. – BIBD

7

Uso table.CreateDataSet

17

Si se ayuda más, aquí es una pieza de código, donde he creado un ClientDataset que se utiliza como una tabla en memoria:

procedure TfrmPRMain.ConfigureDataset; 
begin 
    With cdsMain do begin 
    FieldDefs.Add('bDelete', ftBoolean); 
    FieldDefs.Add('sSource', ftString, 10); 
    FieldDefs.Add('iSection', ftInteger); 
    FieldDefs.Add('iOrder', ftInteger); 
    FieldDefs.Add('sBranch', ftString, 10); 
    FieldDefs.Add('sPulseCode', ftString, 10); 
    FieldDefs.Add('sCode', ftString, 10); 
    FieldDefs.Add('dtWorkDate', ftDate); 
    FieldDefs.Add('iWorkWeek', ftInteger); 
    FieldDefs.Add('sName', ftString, 50); 
    CreateDataSet; 
    LogChanges := False; 
    Open; 
    end; 
end; 

Sólo puede sustituir su propia información de datos y listo. Jack

+3

No necesita la llamada para Abrir. –

+0

El comando "CreateDataSet" provoca una infracción de acceso de nullPointer para mí. (Delphi 10.1 Berlin Starter) –

5

El código de esta página no funciona en CUALQUIER versión de Delphi. Una llamada a CreateDataSet ya pone el conjunto de datos en estado activo ("abierto"). Debería usar .CreateDataSet O .Open. No ambos.

Utilice .Abra cuando desee obtener datos de un proveedor (a través de la propiedad ProviderName) y .CreateDataSet cuando quiera llenar el conjunto de datos usted mismo.

Por cierto: Para una referencia en profundidad acerca de sus características ClientDataSets y echar un vistazo en excelente Cary Jensen articles on CodeGear Developer Network (léase los más antiguos, en primer lugar)

8

No se olvide de incluir midas.dll en su instalación o simplemente incluyen MidasLib en la cláusula de usos. De lo contrario, el uso de TClientDataSet generará un error en la máquina del cliente. Quizás es obvio, pero en realidad lo olvidé una vez.

+2

Si desea incluir MidasLib, tenga en cuenta [este error] (http://stackoverflow.com/q/15449386/2523663). –

1

por alguna razón esto no funciona para mí. Realizo CreateDataset en tiempo de diseño, pero aún bloquea la aplicación. Eso todavía es desconocido para mí. Una advertencia. NO HAGA ESTO:

XXXClientDataSet.Close; 
XXXClientDataSet.Open; 

porque se informará el error. En lugar de Abrir, utilice

xxxClientDataSet.CreateDataset; 

En mi solicitud que necesitaba para restablecer los datos y cargarlo de nuevo, y de nuevo ese mensaje de error causado.

+0

Entonces ... estoy enfrentando el mismo problema. ¿Cuál es la forma correcta de hacer esto, entonces? –

0

Mi preferencia es administrar realmente el conjunto de datos como XML. Puede usar las herramientas de diseño para crear la estructura básica y luego guardarla en el disco. Esto permite que se administre fuera del ejecutable, se compile como un recurso o se administre por separado en el control de versiones.

Al hacerlo de esta manera, puede utilizar LoadFromFile/Stream y las variantes Guardar. Recuerde hacer un uso adecuado de LogChanges y MergeChangeLog según su uso.

3

Si desea un conjunto de datos en memoria libre de dependencia, de alta calidad y rico en funciones (¡sin mencionar el gratuito!), Recomiendo encarecidamente kbmMemTable. Hace todo TClientDataset y luego algo.

+0

Sí, tiene ese método. –

+0

Impresionante conjunto de características. Desafortunadamente, no compilará bajo D2009. –

+0

De acuerdo con su noticia, es compatible con D2009: http://www.components4programmers.com/news/kbmmemtablev_6_00professionalsta.htm –

1

Cementerio piedras a continuación para algunos componentes Libre

En tiempos de Delphi 5/Delphi 7 hubo iniciativas para hacer cualquier objeto con propiedades publicadas (más exactamente - matriz o alguna colección de aquellos) en una base de datos. En Torry.net se trata de CollectionDataSet y Object DataSet años antes de LINQ y demás. Pero dado que el código DB-VCL está poco documentado y es espagueti desde Delphi 1.0 de 16 bits, esos no tienen desarrollo.

También existe un conjunto de datos de objeto Snap basado en retrollamada (basado en eventos), no tan desactualizado. Aunque deja mucho en mi humilde opinión sobre los hombros de los desarrolladores.

La tabla TDBF.sf.net tenía el modo en memoria, pero se eliminó antes. TDBF está muerto también.

rxLib/JediVCL tiene MemoryDataset. Aunque el objetivo rxLib era la compatibilidad de nivel de fuente desde Delphi 1 de 16 bits hasta Delphi 5. Eso paralizó mucho el código. En JVCL tuvo algo de atención y eliminación de código de envejecimiento, pero todavía está medio cocido cuando es necesario algo más profundo que el uso trivial.

También hay componentes de DCU para uso personal como SQLMemoryTable, aunque no para versiones recientes. Me pregunto si Firebird Embedded/SQLite se podría usar para crear una tabla en memoria sin usar hacks de sistema como RAMdrive :-)

0

Este es un código de trabajo corregido mencionado por OP en la primera publicación. Obtiene una tabla de memoria de un TClientDataset que se muestra en DBGrid.

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, DB, DBClient, Grids, DBGrids, StdCtrls, MidasLib; 

type 
    TForm1 = class(TForm) 
    MemTable: TClientDataSet; 
    Button1: TButton; 
    Button2: TButton; 
    DBGrid1: TDBGrid; 
    DataSource1: TDataSource; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    i: word; 
begin 
    MemTable.DisableControls; 
    for i := 1 to 20000 do 
    begin 
    MemTable.Append; 
    MemTable.FieldByName('ID').AsInteger  := i; 
    MemTable.FieldByName('Status').AsString := 'Code'+IntToStr(i); 
    MemTable.FieldByName('Created').AsDateTime := Date(); 
    MemTable.FieldByName('Volume').AsFloat  := Random(10000); 
    MemTable.Post; 
    end; 
    MemTable.EnableControls; 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
begin 
    MemTable.IndexFieldNames := 'Volume'; 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    MemTable.FieldDefs.Add('ID',  ftInteger, 0, False); 
    MemTable.FieldDefs.Add('Status', ftString, 10, False); 
    MemTable.FieldDefs.Add('Created', ftDate, 0, False); 
    MemTable.FieldDefs.Add('Volume', ftFloat, 0, False); 
    MemTable.CreateDataSet; 
end; 

end. 
Cuestiones relacionadas