![]() |
Dataset ADOQuery in ein Clientdataset kopieren
Hallo die Damen und Herren,
mich beschäftigt seit geraumer Zeit ein triviales Problem wie ich vermute. Ich habe eine ADOQuery, gefüllt mit Daten und möchte diese an ein Clientdataset übergeben. Dies gelingt aus nicht nachvollziebaren Gründen nicht. Eine Variante wäre Folgende:
Delphi-Quellcode:
Habe schon eine ganze Menge verschiedene Variante probiert aber es klappt nicht.
procedure TDataContainer.fillupdataset;
var i : Integer; s : String; TempProvider : TDataSetProvider; ClientDataSet1 : TClientDataSet; begin ClientDataSet1 := TClientDataSet.Create(nil); TempProvider := TDataSetProvider.Create(nil); TempProvider.DataSet := fDataContainerDbThread.ADOQuery; i := TempProvider.DataSet.RecordCount; // ist in Ordnung, i ist größer 0 ClientDataSet1.Data := TempProvider.Data; i := ClientDataSet1.RecordCount; // hier ist in i immer 0. Die Übergabe klappt nicht TempProvider.Free; end; Was ist der einfachste Weg, Daten in ein CDS zu duplizieren? Auch wenn ich das CDS mit einem Provider verknüpfe gibt es nicht den gewünschten Erfolg. Zusatzfrage: Alle Komponenten werden in Runtime Created. Welchen Owner kann man hier angeben. Dieser Sollte vom Typ TComponent sein, aber TComponent habe ich nicht, da es keine Formularanwendung ist :| Viele Grüße und vielen Dank |
AW: Dataset ADOQuery in ein Clientdataset kopieren
Moin, ich mache das mit dieser proc. TDM ist einfach nur mein DataModule
Delphi-Quellcode:
procedure TDM.CopyDataSetToCDS(Source: TDataSet; Dest: TClientDataSet; CloseSource: boolean);
var dsProvider: TDataSetProvider; begin {GetText in der Source funktioniert nicht} {Filter in der Source funktioniert} dsProvider:=TDataSetProvider.Create(nil); try dsProvider.DataSet:=Source; Dest.SetProvider(dsProvider); Dest.Open; finally FreeAndNil(dsProvider); end; if CloseSource then Source.Close; end; |
AW: Dataset ADOQuery in ein Clientdataset kopieren
Besten Dank für dein Feedback.
Ich habe eine kleine Demo gemacht und bekomme die gleichen Probleme wie vorher
Delphi-Quellcode:
Ich erwarte an der Stelle
unit DM;
interface uses System.SysUtils, System.Classes, Datasnap.Provider, Data.DB, Datasnap.DBClient; type TDataModule1 = class(TDataModule) cds1: TClientDataSet; private { Private-Deklarationen } public { Public-Deklarationen } procedure testemal(ds : TDataSet); procedure CopyDataSetToCDS(Source: TDataSet; Dest: TClientDataSet; CloseSource: boolean); end; var DataModule1: TDataModule1; implementation {%CLASSGROUP 'System.Classes.TPersistent'} {$R *.dfm} procedure TDataModule1.testemal(ds : TDataSet); var a : Integer; begin a := ds.RecordCount; // in a steht 17, das ist auch korrekt DataModule1.CopyDataSetToCDS( ds, cds1, false ); a := cds1.RecordCount; // in a steht 0. Der Übertrag hat nicht geklappt?! end; procedure TDataModule1.CopyDataSetToCDS(Source: TDataSet; Dest: TClientDataSet; CloseSource: boolean); var dsProvider: TDataSetProvider; begin {GetText in der Source funktioniert nicht} {Filter in der Source funktioniert} dsProvider:=TDataSetProvider.Create(nil); try dsProvider.DataSet:=Source; Dest.SetProvider(dsProvider); Dest.Open; finally FreeAndNil(dsProvider); end; if CloseSource then Source.Close; end; end.
Delphi-Quellcode:
das in a die gleiche Anzahl der Records enthalten ist, wie im dataset ds.
a := cds1.RecordCount
Habe ich hier irgendeinen Gedankenfehler? Das ganze ist in einem Datamodul und die CDS liegt auf der Form. Der Aufruf von testemal kommt von aussen, aber im dataset ds ist injedemfall Inhalt. Es bleibt spannend :roll: |
AW: Dataset ADOQuery in ein Clientdataset kopieren
Nach ewigen probieren bin ich zu einer Variante gelangt die anscheinend funktioniert. Es ist mir allerdings ein totales Rätsel warum das so ist.
Delphi-Quellcode:
Wenn exakt an der Stelle oben im Code
procedure TDataModule1.CopyDataSetToCDS(Source: TDataSet; var Dest: TClientDataSet; CloseSource: boolean);
var dsProvider: TDataSetProvider; I: Integer; a: Boolean; begin {GetText in der Source funktioniert nicht} {Filter in der Source funktioniert} dsProvider:=TDataSetProvider.Create(self); try dsProvider.DataSet:=Source; a := Dest.Data = dsProvider.Data; Dest.SetProvider(dsProvider); Dest.Open; finally FreeAndNil(dsProvider); end; if CloseSource then Source.Close; end; end.
Delphi-Quellcode:
eingefügt wird, dann erhalte ich auch wie erwartet an folgender Stelle den Wert 17
a := Dest.Data = dsProvider.Data;
Delphi-Quellcode:
Allerdings, die zugefügte Codezeile ergibt keinen Sinn.
a := cds1.RecordCount;
Dest.Data ist an der Stelle immer null, a wird immer False. trotzdem passiert irgendwas, dass dazu führt, dass im cds aufeinmal alle Daten drin sind. Ich könnte auch
Delphi-Quellcode:
ergänzen, das hat den selben positiven Effekt.
if Dest.Data = dsProvider.Data then
begin end; Ein Timingproblem scheint es nicht zu sein. Ich habe an der Stelle das Programm durch eine Schleife im Ablauf verzögert. Das hat nichts gebracht. Tja, da weiß ich nicht weiter. Vermutlich fehlt irgendein Schritt mit dem Dest oder dem Provider, der durch die eingefügte Zeile im Hintergrund ausgelöst wird. Viele Grüße und gute Nacht |
AW: Dataset ADOQuery in ein Clientdataset kopieren
Keine Ahnung, was du da gemacht hast. Hier vielleicht noch ein paar Hinweise - zumindest mache ich es so und es funktioniert immer. Bevor der die Copy-Proc aufgerufen wird sollte:
|
AW: Dataset ADOQuery in ein Clientdataset kopieren
Du scheinst, wie Papaschlumpf73 schreibt, auf dem letzten Datensatz zu stehen.
Probiere mal Folgendes aus:
Delphi-Quellcode:
procedure TForm1.CopyDataSetToCDS(Source: TDataSet; Dest: TClientDataSet; CloseSource: boolean);
var dsProvider: TDataSetProvider; inscount: Integer; begin dsProvider := TDataSetProvider.Create(nil); try dsProvider.DataSet := Source; dsProvider.GetRecords(-1, inscount, 0); // !!! Lade alle Records !!! Dest.SetProvider(dsProvider); Dest.Open; finally FreeAndNil(dsProvider); end; if CloseSource then Source.Close; end; |
AW: Dataset ADOQuery in ein Clientdataset kopieren
Ich kann mich nur bei euch bedanken.
Sowohl den Sourcedatensatz auf .First setzen als auch die GetRecords Variante führen zum gewünschten Ergebnis. Soviele verschiedene Varianten die ich probiert habe aber auf die triviale Idee bin ich nicht gekommen. Vielen Lieben Dank an euch! |
AW: Dataset ADOQuery in ein Clientdataset kopieren
Hallo, ich muss euch doch nochmal belästigen.
Grundsätzlich dachte ich, dass es funktioniert. Das tut es auch allerdings nur im ersten Durchlauf. Danach wird das ZielCds nicht erneut aktualisiert. Folgende 2 Varianten habe ich erstellt: Einmal mit einem CDS das global erstellt wurde und bei jedem Durchlauf geleert werden soll:
Delphi-Quellcode:
testCDS_global : TClientDataSet; ... testCDS_global := TClientDataSet.Create(self);
Delphi-Quellcode:
Diese Prozedur füllt das testCds nur beim ersten Durchlauf, sobald das CDS einmal erstellt, gefüllt und beim Durchlauf EmptyDataSet gemacht wurde, dann klappt das nicht mehr.
procedure TDataContainer.fillupdataset;
var a,b : Integer; begin try if testCDS_global.Active then begin testCDS_global.Open; testCDS_global.EmptyDataSet; end; except a:=a; end; try // a = Anzahl der Einträge im ADOquery dataset a := fDataContainerDbThread.ADOQuery.RecordCount; CopyDataSetToCDS( fDataContainerDbThread.ADOQuery, testCDS_global, false ); b := testCDS_global.RecordCount; finally end; end; Folgende Prozedur führt zu einer Aktualisierung bei jedem Durchlauf:
Delphi-Quellcode:
Heißt, es muss einen Unterschied zwischen einem neu createden CDS und einem CDS das mit EmptyDataSet behandelt wurde geben.
procedure TDataContainer.fillupdataset2;
var a,b : Integer; testCDS_lokal : TClientDataSet; begin testCDS_lokal := TClientDataSet.Create(nil); try // a = Anzahl der Einträge im ADOquery dataset a := fDataContainerDbThread.ADOQuery.RecordCount; CopyDataSetToCDS( fDataContainerDbThread.ADOQuery, testCDS_lokal, false ); b := testCDS_lokal.RecordCount; finally FreeAndNil(testCDS_lokal); end; end; Ich komme nicht drauf :cyclops: Vollständigkeitshalber:
Delphi-Quellcode:
Zusatzfrage:
procedure TDataContainer.CopyDataSetToCDS(Source: TDataSet; Dest: TClientDataSet; CloseSource: boolean);
var dsProvider: TDataSetProvider; a,b : Integer; begin dsProvider := TDataSetProvider.Create(nil); try Source.First; dsProvider.DataSet := Source; dsProvider.GetRecords(-1, a, 0); // !!! Lade alle Records !!! Dest.SetProvider(dsProvider); Dest.Open; finally FreeAndNil(dsProvider); end; if CloseSource then Source.Close; end; Wenn die Variable dsProvider auf FreeAndNil gesetzt wird, woher kennt das das Sourcedataset im Anschluss dann noch seinen Provider? Das scheint an dieser Stelle egal zu sein? Der dsProvider ist ja ohnehin nur in dieser Prozedur verfügbar.. |
AW: Dataset ADOQuery in ein Clientdataset kopieren
Das hier ist schon mal nicht so toll.
Delphi-Quellcode:
Wenn das CDS aktiv ist, dann soll er es öffnen? Nein, das kann es nicht sein.
if testCDS_global.Active then
begin testCDS_global.Open; testCDS_global.EmptyDataSet; end; Das würde ich erstmal ändern in:
Delphi-Quellcode:
Dann hast du für die Copy-proc ein leeres, geschlossenes ClientDataSet.
if testCDS_global.Active then
begin testCDS_global.EmptyDataSet; testCDS_global.Close; end; |
AW: Dataset ADOQuery in ein Clientdataset kopieren
An der Stelle habe ich auch schon probiert. Ich bekomme beim Close immer einen "schwerwiegenden Fehler" angezeigt.
Aus diesem Grund habe ich das Close wieder entfernt. Aber grundsätzlich macht das Sinn was du schreibst. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz