2009-06-29 7 views

Répondre

1

Vous pouvez créer un nouveau jeu de données en utilisant l'ancien FieldDefs de l'ensemble de données. Le point clé est TFieldDefs.Assign. Voici un petit exemple:

// insert test data 
procedure TForm1.InsertRecord(DataSet: TDataSet; ID: Integer; const Name: string); 
begin 
    DataSet.Insert; 
    try 
    DataSet.Fields[0].AsInteger := ID; 
    DataSet.Fields[1].AsString := Name; 
    DataSet.Post; 
    except 
    DataSet.Cancel; 
    raise; 
    end; 
end; 

// create the original dataset 
procedure TForm1.Button1Click(Sender: TObject); 
var 
    DataSet: TClientDataSet; 
begin 
    DataSet := TClientDataSet.Create(nil); 
    try 
    DataSet.FieldDefs.Add('ID', ftInteger); 
    DataSet.FieldDefs.Add('NAME', ftString, 20); 
    DataSet.CreateDataSet; 
    DataSet.LogChanges := False; 
    InsertRecord(DataSet, 1, 'Hello'); 
    InsertRecord(DataSet, 2, 'World!'); 
    DataSet.SaveToFile(ExtractFilePath(Application.ExeName) + 'old.xml', dfXML); 
    finally 
    DataSet.Free; 
    end; 
end; 

// create the new dataset 
procedure TForm1.Button2Click(Sender: TObject); 
var 
    OldDataSet, NewDataSet: TClientDataSet; 
begin 
    OldDataSet := nil; 
    NewDataSet := nil; 
    try 
    OldDataSet := TClientDataSet.Create(nil); 
    OldDataSet.LoadFromFile(ExtractFilePath(Application.ExeName) + 'old.xml'); 

    NewDataSet := TClientDataSet.Create(nil); 
    NewDataSet.FieldDefs.Assign(OldDataSet.FieldDefs); 
    NewDataSet.FieldDefs[1].Size := 30; 
    NewDataSet.CreateDataSet; 
    NewDataSet.LogChanges := False; 

    OldDataSet.First; 
    while not OldDataSet.EOF do 
    begin 
     InsertRecord(NewDataSet, OldDataSet.Fields[0].AsInteger, OldDataSet.Fields[1].AsString); 

     OldDataSet.Next; 
    end; 

    NewDataSet.SaveToFile(ExtractFilePath(Application.ExeName) + 'new.xml', dfXML); 
    finally 
    OldDataSet.Free; 
    NewDataSet.Free; 
    end; 
end; 
+0

Merci TOndrej. Un peu plus tôt, je l'ai résolu de la même manière. Un CDS «pre» ouvrira un fichier xml. Ensuite, une procédure copiera le fielddefs (méthode assign) à partir du CDS de destination pré-CDS->. Ensuite, les fielddefs sont vérifiés pour les noms de champs qui pourraient avoir la mauvaise taille lorsque cela est corrigé. Après cela, les valeurs du pré-CDS sont copiées dans le CDS de destination. Dans ce processus de copie, les événements sont définis sur zéro et de nouveau à la fin. La même chose avec les champs en lecture seule. Le CDS de destination enregistre dans le fichier XML. En vérifiant ce fichier, cette procédure semble fonctionner correctement. – xsintill

3

La façon dont le TDataSet est implémenté, il existe des méthodes virtuelles pour allouer et libérer le tampon d'enregistrement et pour obtenir et définir des valeurs à partir de ce tampon. La plupart des descendants de jeux de données conservent un bloc de mémoire contiguë pour le tampon, donc si vos trois champs ont quatre, six et vingt octets, le champ 1 commencera à la position 0, le champ 2 à la position quatre et le champ 3 à la position dix.

Si vous souhaitez modifier la taille d'un champ alors que l'ensemble de données est ouvert, tous ces tampons doivent être redimensionnés et ajustés, sinon vous rencontrerez des problèmes. Il n'y a pas de méthode virtuelle pour redimensionner le tampon, donc je dirais que ce n'est probablement pas faisable.

La façon de procéder est de copier votre contenu du CDS original vers un nouveau avec différentes tailles de champs. Affectez-lui la valeur par valeur ou utilisez un TDataSetProvider. Si vous utilisez le fournisseur (meilleure approche) et que vous ne connaissez pas la définition exacte, vous devez toujours parcourir les champs de l'ensemble de données source et les ajouter à la destination avec la taille correcte.

Questions connexes