2010-03-30 17 views
3

EDIT: Il semble que le DataSetProvider ne possède pas les fonctionnalités dont j'ai besoin pour ce projet, donc je vais implémenter une classe personnalisée pour charger les données dans le ClientDataSet.DataSetProvider - DataSet à ClientDataSet

J'essaie de prendre des données à partir d'un TMSQuery qui est connecté à ma base de données et de remplir un ClientDataSet avec certaines de ces données en utilisant un DataSetProvider.

Mon problème est que je vais devoir modifier certaines de ces données avant de pouvoir aller dans mon ClientDataSet. ClientDataSet a des champs persistants qui ne correspondent pas aux données de base de données brutes. Je ne peux même pas obtenir une chaîne de la base de données dans un champ Mémo dans ClientDataSet. Le ClientDataSet est une partie de mon niveau de données, donc je devrai conformer les données de la base de données au champ ClientDataSet par champ (bien que la plupart puissent passer à travers, mais beaucoup nécessiteront le routage et/ou la conversion).

Est-ce que quelqu'un a de l'expérience avec ça?

Répondre

0

Si j'ai besoin d'un ClientDataSet pour avoir des données qui ne correspondent pas exactement au schéma de base de données, j'écris une requête pour le composant TQuery qui retourne les données au format que je veux. J'écris ensuite mes propres requêtes, séparées, Delete, Insert, Refresh et Update pour le composant TQuery.

Vous pouvez également créer une vue sur la base de données et utiliser la vue dans votre composant TQuery.

Si vous voulez un ClientDataSet personnalisé indépendant de la base de données, vous avez besoin d'un ensemble de données en mémoire. Si vous ne possédez pas de composant de jeu de données en mémoire, Google pour "TClientDataSet en tant que jeu de données en mémoire". Ce que vous finissez cependant avec, est fondamentalement un composant glorifié de vue de liste. Bien sûr, vous pouvez vous connecter au OnUpdateRecord du jeu de données en mémoire pour savoir quand mettre à jour votre jeu de données réel.

2

Vous recherchez l'événement TDataSetProvider.BeforeUpdateRecord. Ecrivez un gestionnaire d'événements pour cet événement et vous pouvez contrôler manuellement la manière dont les données sont appliquées à la base de données.

Quelque chose comme ça

procedure TDataModule1.DataSetProvider1BeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); 
begin 
    { Set applied to tell DataSnap that you have applied this record yourself } 
    Applied := True; 

    case UpdateKind of 
    ukModify: 
     begin 
     Table1.Edit; 
     { set the values of the fields something like this } 
     if not VarIsEmpty(DeltaDS.FieldByName('NewValue')) then 
      Table1['SomeField'] := DeltaDS.FieldByName('SomeField').NewValue; 
     Table1.Post; 
    end; 

    ukInsert: 
     begin 
     Table1.Insert; 
     { set the values of the fields } 
     Table1['SomeField'] := DeltaDS['SomeField'] 
     Table1.Post; 
     end; 

    ukDelete: 
     if Table1.Locate('PrimaryKeyField', DeltaDS['PrimaryKeyField'], []) then 
     Table1.Delete; 
    end; // case 
end; 
+0

+1 très similaire au résolveur kbmMemTable juste à l'envers. –

+0

Je devrai le faire, mais pas jusqu'à ce que je sois capable d'obtenir les données dans le ClientDataSet. Je dois pouvoir apporter les mêmes modifications aux données provenant du DataSet connecté à la base de données. C'est possible? – LostNomad311

+0

Il semble que vous souhaitiez combiner les données de 2 tables ou plus en un seul ClientDataSet, puis appliquer les mises à jour aux tables source. Si c'est vraiment possible, je veux juste vérifier avant de modifier ma réponse. – LachlanG

0

Vous pouvez modifier les données en cours de ClientDataSet en mettant en œuvre l'événement TDataSetProvider.OnGetData.

procedure TDataModule1.DataSetProvider1GetData(Sender: TObject; DataSet: TCustomClientDataSet); 
begin 
    DataSet.First; 
    while not DataSet.Eof do begin 
    DataSet.Edit; 
    DataSet['Surname'] := UpperCase(DataSet['Surname']); 
    DataSet.Post; 
    DataSet.Next; 
    end; // while 
end; 

Lors de l'application des mises à jour de ClientDataSet vous pouvez utiliser l'événement TDataSetProvider.OnUpdateData. Comme l'événement OnGetData, vous travaillez sur l'ensemble de données plutôt que sur un seul enregistrement.

procedure TDataModule1.DataSetProvider1UpdateData(Sender: TObject; DataSet: TCustomClientDataSet); 
begin 
    DataSet.First; 
    while not DataSet.Eof do begin 
    DataSet.Edit; 
    DataSet['Surname'] := LowerCase(DataSet['Surname']); 
    DataSet.Post; 
    DataSet.Next; 
    end; // while 
end; 

Cet événement OnUpdateData est appelé avant l'événement OnBeforeUpdateRecord. Les événements OnGetData et OnUpdateData fonctionnent également sur l'ensemble de données entier tandis que OnBeforeUpdateRecord est appelé une fois pour chaque enregistrement modifié.

+0

J'ai regardé dans l'événement OnGetData, mais les données sont déjà dans le ClientDataSet à ce stade. Le problème est que mes types de données ne correspondent pas donc quelque chose d'aussi simple qu'un StringField dans TMSQuery ne peut pas charger dans un MemoField dans le ClientDataSet, donc je reçois une exception. – LostNomad311

+0

Pouvez-vous faire les transformations dont vous avez besoin dans le SQL, en transformant les chaînes en mémos etc? – LachlanG

+0

Je pourrais, mais cela créerait un autre point d'accès DB indésirable. La solution que j'implémente est une classe personnalisée pour charger les données dans le ClientDataSet. J'aimerais utiliser ce fournisseur, mais il n'a pas la fonctionnalité dont j'ai besoin. – LostNomad311