AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi TADOQuery asynchron abfragen
Thema durchsuchen
Ansicht
Themen-Optionen

TADOQuery asynchron abfragen

Ein Thema von Norbert5 · begonnen am 6. Nov 2009 · letzter Beitrag vom 10. Nov 2009
Antwort Antwort
Norbert5

Registriert seit: 6. Nov 2009
6 Beiträge
 
#1

TADOQuery asynchron abfragen

  Alt 6. Nov 2009, 09:29
Datenbank: MS SQL Server 2005 • Zugriff über: ADO
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.
  Mit Zitat antworten Zitat
Norbert5

Registriert seit: 6. Nov 2009
6 Beiträge
 
#2

Re: TADOQuery asynchron abfragen

  Alt 10. Nov 2009, 00:11
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
- bei asynchronem Execute auf den 2. Datensatz

Muss ich mich jetzt bei Microsoft beschweren?
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.197 Beiträge
 
Delphi 10.4 Sydney
 
#3

Re: TADOQuery asynchron abfragen

  Alt 10. Nov 2009, 08:34
Welche Delphi-Version hast du den? Alle Updates installiert?
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von simmi
simmi

Registriert seit: 24. Nov 2004
Ort: Röbel/Müritz
112 Beiträge
 
Delphi XE5 Professional
 
#4

Re: TADOQuery asynchron abfragen

  Alt 10. Nov 2009, 08:51
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.
Uwe
  Mit Zitat antworten Zitat
Norbert5

Registriert seit: 6. Nov 2009
6 Beiträge
 
#5

Re: TADOQuery asynchron abfragen

  Alt 10. Nov 2009, 10:11
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
  Mit Zitat antworten Zitat
Norbert5

Registriert seit: 6. Nov 2009
6 Beiträge
 
#6

Re: TADOQuery asynchron abfragen

  Alt 10. Nov 2009, 11:27
Noch ein Nachtrag:

Inzwischen habe ich bei Microsoft zwei verwandte Einträge in der Fehler-Datenbank gefunden:

http://kbupdate.info/microsoft-data-...ac-2-6-bug.php

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.

Meine Begeisterung wächst stündlich ...
  Mit Zitat antworten Zitat
Norbert5

Registriert seit: 6. Nov 2009
6 Beiträge
 
#7

Re: TADOQuery asynchron abfragen

  Alt 10. Nov 2009, 23:26
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:
            
             if not Recordset.EOF then
               Recordset.MoveNext;
neu:
Delphi-Quellcode:
            
              if not Recordset.EOF then
              begin
                if Recordset.BOF
                  then Recordset.MoveFirst
                  else Recordset.MoveNext;
              end;
Vielen Dank für Eure Bemühungen.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:49 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz