![]() |
Datenbank: MS SQL Server 2005 • Zugriff über: ADO
TADOQuery asynchron abfragen
Ich verbinde eine TADOQuery mit einem DBGrid.
Damit der Benutzer nicht auf das komplette SQL warten muss, arbeite ich asynchron. Das Grid zeigt aber grundsätzlich den 2. Datensatz als ersten an. Erst nach einem Next/Prior/Prior komme ich zum 1. Datensatz. Ebenso positioniert ein First wieder auf Datensatz 2. Offensichtlich ist BOF true beim 2. Datensatz! Synchron sind Query und Grid okay. Hat jemand eine Idee? Hier mein Code: [delphi] type TForm3 = class(TForm) PF32DB: TADOConnection; DataSource1: TDataSource; OVCDBTable1: TDBGrid; DBNavigator1: TDBNavigator; Button1: TButton; ADOTable1: TADOQuery; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private-Deklarationen } isexecuting: boolean; iscanceling: boolean; aktreccnt: integer; iworkasync: boolean; procedure OpenTable; procedure _onFetchProgress(DataSet: TCustomADODataSet; Progress, MaxProgress: Integer; var EventStatus: TEventStatus); procedure _onFetchComplete(DataSet: TCustomADODataSet; const Error: Error; var EventStatus: TEventStatus); public procedure WaitForFirstData; procedure WaitForAllData; property Executing: boolean read isexecuting; public { Public-Deklarationen } end; var Form3: TForm3; const workasync = true; implementation {$R *.dfm} procedure TForm3.Button1Click(Sender: TObject); begin ADOTable1.first; end; procedure TForm3.FormCreate(Sender: TObject); begin PF32DB.Connected := true; with ADOTable1 do begin SQL.Clear; SQL.Add('Select * from PFPK where tbljahr=2009'); OpenTable; end; end; procedure TForm3.OpenTable; begin iworkasync := workasync; isexecuting := false; aktreccnt := 0; with ADOTable1 do begin if active then //already opened/closed? exit; if not assigned(Connection) then iworkasync := false; if (csDesigning in ComponentState) then //no async in Designer iworkasync := false; if not iworkasync then begin ExecuteOptions := []; active := true; exit; end; DisableControls; ExecuteOptions := ExecuteOptions + [eoAsyncExecute, eoAsyncFetch{, eoAsyncFetchNonblocking}]; isexecuting := true; iscanceling := false; OnFetchProgress := _OnFetchProgress; OnFetchComplete := _OnFetchComplete; aktreccnt := 0; active := true; while (isexecuting and (aktreccnt=0))do //wait for first datablock application.ProcessMessages; EnableControls; end; end; procedure TForm3.WaitForFirstData; begin if (csDesigning in ComponentState) then exit; while (isexecuting and (aktreccnt=0))do application.ProcessMessages; end; procedure TForm3.WaitForAllData; begin if (csDesigning in ComponentState) then exit; while isexecuting do application.ProcessMessages; end; procedure TForm3._onFetchProgress(DataSet: TCustomADODataSet; Progress, MaxProgress: Integer; var EventStatus: TEventStatus); begin if Progress=MaxProgress then begin isexecuting := false; exit; end; if (iscanceling and assigned(Dataset) and assigned(Dataset.Recordset)) then begin Dataset.Recordset.Cancel; end; aktreccnt := Progress; end; procedure TForm3._onFetchComplete(DataSet: TCustomADODataSet; const Error: Error; var EventStatus: TEventStatus); begin isexecuting := false; iscanceling := false; end; end. |
Re: TADOQuery asynchron abfragen
:wall: Nach einigen Stunden im Debugger (bei asynchronen Routinen macht das Debuggen doppelt Spass) bin ich ein wenig schlauer.
Aber geholfen hat's noch nicht. TDataSet.First ruft zuerst InternalFirst auf, bei ADO bedeutet dies MoveFirst + MovePrevious => recordset-objekt wird vor den ersten Satz gesetzt; recordset.bof ist true Danach wird GetNextRecord aufgerufen, resultiert in recordset.MoveNext. so weit, so logisch Aber: steht der ADO-Recordset auf BOF, positioniert recordset.MoveNext - bei synchronem Execute auf den 1. Datensatz :-D - bei asynchronem Execute auf den 2. Datensatz :gruebel: Muss ich mich jetzt bei Microsoft beschweren? |
Re: TADOQuery asynchron abfragen
Welche Delphi-Version hast du den? Alle Updates installiert?
|
Re: TADOQuery asynchron abfragen
Hallo,
ich hatte das gleiche Problem mit ADO. Es wurde sogar noch schlimmer, weil irgendwann die ganzen Datensätze durcheinander waren. Als brauchbare Lösung erwies sich, statt mit ADO mit SQL Direkt zu arbeiten. Das funktioniert schnell und bisher Problemlos. |
Re: TADOQuery asynchron abfragen
Erstmal Dank für eure Antworten.
Zu 1: Probiert (und den Fehler reproduziert) habe ich mit Delphi-7 und RAD-Studio 2007. Zu 2: Mit TSQLQuery kann ich keine asynchrone Bearbeitung machen oder habe ich da was übersehen :?: |
Re: TADOQuery asynchron abfragen
Noch ein Nachtrag:
Inzwischen habe ich bei Microsoft zwei verwandte Einträge in der Fehler-Datenbank gefunden: ![]() Nr. 287083 (Mai 2003) - first row not stored if bound to controlelement Nr. 245509 (März 2005) - error "Async operation is pending" In beiden Fällen bestätigt Microsoft einen eigenen Fehler; Zu 1 empfiehlt MS, mit einem Recordset-Clone zu arbeiten (das würde Delphis Tabellensteuerung völlig aus der Bahn werfen) oder Server-Cursor zu verwenden (hat bei mir das Verhalten nicht geändert) Zu 2 rät MS zur Umstellung auf synchrone Bearbeitung - sehr sinnig. :angel: Meine Begeisterung wächst stündlich ... |
Re: TADOQuery asynchron abfragen
:cheers: Heureka, ich hab's gefunden.
Den Fehler von Microsoft kann ich nicht korrigieren, aber eine kleine Änderung in ADODB umgeht diesen Fehler. Routine TCustomADODataSet.InternalGetRecord (RAD Studio 2007: Zeile 4179) bisher:
Delphi-Quellcode:
neu:if not Recordset.EOF then Recordset.MoveNext;
Delphi-Quellcode:
Vielen Dank für Eure Bemühungen.if not Recordset.EOF then begin if Recordset.BOF then Recordset.MoveFirst else Recordset.MoveNext; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:50 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