web-dev-qa-db-fra.com

Delphi: utiliser TClientDataset en tant que jeu de données en mémoire

Selon cette page, il est possible d’utiliser TClientDataset en tant que jeu de données en mémoire, totalement indépendant de toute base de données ou de tout fichier. Il décrit comment configurer la structure de la table du jeu de données et comment y charger des données lors de l'exécution. Mais lorsque j'ai essayé de suivre ses instructions dans D2009, l'étape 4 (table.Open) a déclenché une exception. Il a dit qu'il n'a pas eu un fournisseur spécifié.

L’exemple de cette page a pour but de créer un ensemble de données qui n’a pas besoin d’un fournisseur. La page est-elle erronée, obsolète ou manque-t-il une étape quelque part? Et si la page est incorrecte, que dois-je utiliser à la place pour créer un jeu de données en mémoire complètement indépendant? J'utilise TJvMemoryData, mais si possible, j'aimerais réduire le nombre de dépendances supplémentaires que mon jeu de données ajoute à mon projet.

20
Mason Wheeler

Au moment de l'exécution, vous pouvez utiliser table.CreateDataset ou, s'il s'agit d'une surface de conception, vous pouvez cliquer avec le bouton droit de la souris sur le CDS et cliquer sur Créer un jeu de données. Vous devez cependant avoir spécifié des colonnes/types pour le CDS avant de pouvoir le faire.

21
MikeJ

Si cela peut vous aider, voici un morceau de code dans lequel j'ai créé un ClientDataset qui est utilisé comme table en mémoire:

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;

Vous pouvez simplement substituer vos propres informations de données et aller. Jack

20
jrodenhi

N'oubliez pas d'inclure MIDAS.DLL dans votre installation ou tout simplement d'inclure MidasLib dans la clause uses. Sinon, utiliser TClientDataSet provoquera une erreur sur la machine du client. C'est peut-être évident, mais j'ai en fait oublié cela une fois.

8
vrad

Vous pouvez utiliser table.CreateDataSet

7
Tom

Le code de cette page ne fonctionne dans AUCUNE version de Delphi. Un appel à CreateDataSet met déjà l'ensemble de données en état actif ("ouvert"). Vous devez utiliser .CreateDataSet OR .Open. Pas les deux.

Utilisez .Open lorsque vous souhaitez extraire des données d'un fournisseur (via la propriété ProviderName) et .CreateDataSet lorsque vous souhaitez renseigner vous-même le jeu de données.

BTW: Pour une référence détaillée sur ClientDataSets et ses fonctionnalités, regardez d'excellents Articles de Cary Jensen sur CodeGear Developer Network (lisez les plus anciens, en premier)

5
F.D.Castel

Si vous souhaitez un jeu de données en mémoire riche, sans dépendance, de haute qualité et riche en fonctionnalités (pour ne pas mentionner libre!), Je vous recommande vivement kbmMemTable . Est-ce que tout TClientDataset fait et puis certains.

3
Tim Sullivan

pour une raison quelconque, cela ne fonctionne pas pour moi. J'exécute CreateDataset au moment du design, mais l'application se bloque quand même. Cela m'est toujours inconnu. Un avertissement. NE FAITES PAS CELA:

XXXClientDataSet.Close;
XXXClientDataSet.Open;

car il va signaler une erreur. Au lieu de Open, utilisez 

xxxClientDataSet.CreateDataset;

Dans mon application, je devais réinitialiser les données et les charger à nouveau, ce qui provoquait à nouveau un message d'erreur.

1
Simon

Pierres de cimetière ci-dessous pour certaines composantes libres

À l'époque de Delphi 5/Delphi 7, il y avait des initiatives pour transformer n'importe quel objet avec des propriétés publiées (plus précisément - un tableau ou une collection de celles-ci) dans une base de données. Sur Torry.net, il s’agit de CollectionDataSet et Object DataSet . Plusieurs années avant LINQ et autres. Mais depuis que le code DB-VCL est peu documenté et spaghetti depuis 16 bits ceux-ci n'ont pas de développement.

Il existe également un jeu de données d'objet de capture basé sur des rappels (basé sur des événements), qui n'est pas aussi obsolète. Bien que cela laisse trop de mon humble avis sur les épaules des développeurs.

La table TDBF.sf.net avait le mode en mémoire, mais a été retirée tôt. TDBF est mort aussi.

rxLib/JediVCL a MemoryDataset. Bien que la cible rxLib soit une compatibilité au niveau de la source depuis Delphi 1 16 bits jusqu'à Delphi 5. Cela a beaucoup handicapé le code. Dans JVCL, il y avait un peu d'attention et de suppression du code vieillissant, mais il est encore à moitié cuit lorsqu'il est nécessaire d'utiliser un usage plus profond que trivial.

Il existe également des composants DCU gratuits comme Personal, tels que SQLMemoryTable, mais pas pour les versions récentes. Je me demande si Firebird Embedded/SQLite pourrait être utilisé pour créer un tableau en mémoire sans utiliser de piratage système tel que RAMdrive :-)

1
Arioch 'The

Pour moi, cela était dû à une incompatibilité midas.dll. Je l'ai corrigé en ajoutant MidasLib à la clause uses du programme principal (liant ainsi la bibliothèque de manière statique). Plus d'infos ici: http://codeverge.com/embarcadero.datasnap/tclientdataset-createdataset-failing-wit/1097715 et ici: http://edn.embarcadero.com/article/29297

0
Ludecan

Ma préférence est de gérer le jeu de données en tant que XML. Vous pouvez utiliser les outils du concepteur pour créer la structure de base, puis l'enregistrer sur le disque. Cela lui permet d'être géré en dehors de l'exécutable, compilé en tant que ressource ou géré séparément dans le contrôle de version.

En procédant de cette manière, vous pouvez utiliser LoadFromFile/Stream et les variantes Save. N'oubliez pas d'utiliser correctement LogChanges et MergeChangeLog en fonction de votre utilisation.

0

Il s'agit d'un code de travail corrigé mentionné par OP dans le premier message. Vous obtenez une table mémoire à partir d'une TClientDataset affichée dans 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.
0
avra