Delphi: utiliser TClientDataset comme un ensemble de données en mémoire
Selon cette page il est possible d'utiliser TClientDataset
comme un dataset en mémoire, totalement indépendant de bases de données ou fichiers. Il décrit comment configurer la structure de la table de l'ensemble de données et comment y charger des données à l'exécution. Mais quand j'ai essayé de suivre ses instructions dans D2009, étape 4 (table.Open
) a soulevé une exception. Il a dit qu'il n'avait pas un fournisseur spécifié.
le point entier de l'exemple sur cette page est de construire un ensemble de données qui n'a pas besoin d'un prestataire. La page est mal, est-il obsolète, ou ai-je raté une étape quelque part? Et si la page est erronée, que dois-je utiliser à la place pour créer un ensemble de données complètement indépendant en mémoire? J'ai été en utilisant TJvMemoryData
, mais si possible j'aimerais réduire la quantité supplémentaire de dépendances que mon dataset ajoute dans mon projet.
11 réponses
à l'exécution, vous pouvez utiliser table.CreateDataset
ou si c'est sur une surface de dessin, vous pouvez cliquer droit sur le CD et cliquez sur créer un dataset. Vous devez avoir des colonnes/types spécifiés pour les CDS avant de pouvoir le faire.
si cela aide plus loin, voici un morceau de code où j'ai créé un ClientDataset qui est utilisé comme une 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 remplacer vos propres informations de données et aller. Jack
N'oubliez pas D'inclure MIDAS.DLL dans votre installation ou tout simplement inclure MidasLib dans la clause d'utilisation. Autrement en utilisant TClientDataSet
déclenchera une erreur sur la machine du client. C'est peut-être évident, mais j'ai oublié cette fois.
le code de cette page ne fonctionne dans aucune version Delphi. Un appel à CreateDataSet met déjà l'ensemble de données en état actif ("ouvert"). Tu devrais l'utiliser .CreateDataSet OR .Ouvrir. Pas les deux.
Utilisation .Ouvrez lorsque vous voulez récupérer des données d'un fournisseur (via la propriété ProviderName) et .CreateDataSet quand vous voulez peupler l'ensemble de données par vous-même.
BTW: pour une référence en profondeur sur les données client et ses fonctionnalités, jetez un oeil sur excellent Cary Jensen articles sur CodeGear Developer Network (lire les plus anciennes, d'abord)
si vous souhaitez un sans dépendance, de haute qualité, et riche en fonctionnalités (sans mentionner gratuit!) dataset en mémoire, je recommande fortement kbmMemTable. Fait tout TClientDataset
et puis certains.
Cimetière pierres ci-dessous pour quelques libre composants
dans les temps de Delphi 5 / Delphi 7 Il y avait des initiatives pour faire n'importe quel objet avec des propriétés publiées (plus précisément - tableau ou une certaine collection de ceux-ci) dans une base de données. Sur Torry.net il S'agit de CollectionDataSet et D'un ensemble de données D'objets Des années avant LINQ. Mais depuis DB-VCL code est peu documenté et est spaghetti depuis 16-bit Delphi 1.0 - ceux-ci n'ont pas de développement.
Il y a aussi ensemble de données Snap Object basé sur le rappel (basé sur les événements), pas si désuet. Bien qu'il laisse trop D'IMHO sur les épaules des développeurs.
TDBF.sf.net table avait le mode mémoire, mais a été retiré tôt. TDBF est mort aussi.
rxLib/JediVCL has MemoryDataset. Bien que la cible de rxLib était compatible au niveau de la source depuis 16-bit Delphi 1 jusqu'à Delphi 5. Qui a paralysé le code beaucoup. Dans JVCL il a eu une certaine attention et la suppression du code de vieillissement, mais est toujours à moitié cuit lorsque nécessaire plus profond que négligeable d'utilisation.
Il y a aussi des composants DCU gratuits pour le personnel comme SQLMemoryTable, mais pas pour les versions récentes. Je me demande si Firebird Embedded / SQLite pourrait être utilisé pour créer une table en mémoire sans utiliser des hacks à l'échelle du système comme RAMdrive : -)
pour une raison que ça ne fonctionne pas pour moi. J'ai effectuer CreateDataset
dans le temps de conception, mais il se bloque encore application. Qui est encore inconnu pour moi.
Un avertissement. DO NOT DO THIS:
XXXClientDataSet.Close;
XXXClientDataSet.Open;
parce qu'il signalera une erreur. Au lieu de Open
, utilisez
xxxClientDataSet.CreateDataset;
dans mon application, j'avais besoin de réinitialiser les données et de les charger à nouveau, et cela a encore causé un message d'erreur.
Ma préférence est de gérer l'ensemble de données en XML. Vous pouvez utiliser les outils du concepteur pour créer la structure de base et ensuite la sauvegarder sur le disque. Cela lui permet d'être géré à l'extérieur de l'exécutable compilé en tant que ressource, ou gérés séparément dans le contrôle de version.
lorsque vous le faites de cette façon, vous pouvez utiliser LoadFromFile/Stream et les variantes de sauvegarde. N'oubliez pas d'utiliser correctement les LogChanges et MergeChangeLog en fonction de votre usage.
Pour moi, cela a été causé par un midas.incompatibilité dll. Je l'ai corrigé en ajoutant MidasLib aux programmes principaux utilise la clause (liant ainsi statiquement la bibliothèque). Plus d'infos ici: http://codeverge.com/embarcadero.datasnap/tclientdataset-createdataset-failing-wit/1097715 et ici: http://edn.embarcadero.com/article/29297
il s'agit d'un code de travail corrigé mentionné par OP dans le premier message. Vous obtenez une table de mémoire d'un TClientDataset
affiché 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.