【发布时间】:2016-02-22 16:14:47
【问题描述】:
我正在尝试异步执行 sql 查询。我检查了来自http://docwiki.embarcadero.com/RADStudio/XE5/en/Asynchronous_Execution_(FireDAC)的示例代码
还有目录中的示例项目
..Samples\Object Pascal\Database\FireDAC\Samples\Comp Layer\TFDQuery\ExecSQL\Async
我想我明白了里面的逻辑。但是有一个问题 - 事件QueryAfterOpen 永远不会执行,而我的TDataSource 始终保持Nil(因为它在QueryBeforeOpen 中得到Nil - 此事件始终执行)。这是我单位的所有代码:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf,
FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,
FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
Vcl.StdCtrls, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client,
FireDAC.Phys.MySQLDef, FireDAC.Phys.MySQL;
type
TForm1 = class(TForm)
Button1: TButton;
FDPhysMySQLDriverLink1: TFDPhysMySQLDriverLink;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Query1BeforeOpen(DataSet: TDataSet);
procedure Query1AfterOpen(DataSet: TDataSet);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
Connection1: TFDConnection;
Query1: TFDQuery;
DataSource1: TDataSource;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
QueryFinished: Boolean;
begin
with Query1 do begin
SQL.Text := 'SELECT field1 FROM test_table WHERE idpk=1';
AfterOpen := Query1AfterOpen;
BeforeOpen := Query1BeforeOpen;
ResourceOptions.CmdExecMode := amAsync;
QueryFinished := False;
Open;
repeat
Sleep(100);
if Command.State = csPrepared then begin
// A command is prepared. A result set is not accessible.
// TmpInteger := Query1.FieldByName('field1').AsInteger;
end
else if Command.State = csOpen then begin // A command execution
// is finished. A result set is accessible and not yet fully fetched.
if DataSource1.DataSet <> Nil then begin
// this code never executes because Query1AfterOpen never executes and
// DataSource1.DataSet remains always Nil !!!
QueryFinished := True;
end;
end;
until ((QueryFinished) OR (DataSource1.DataSet <> Nil));
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
SQLConnParams: string;
begin
SQLConnParams := ''; // sql connection parameters removed from here from security
// issues, assume they are correct
Connection1 := TFDConnection.Create(Nil);
Connection1.Params.Text := SQLConnParams;
Query1 := TFDQuery.Create(Nil);
Query1.Connection := Connection1;
DataSource1 := TDataSource.Create(Nil);
DataSource1.DataSet := Query1;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
DataSource1.Free;
Query1.Free;
Connection1.Free;
end;
procedure TForm1.Query1AfterOpen(DataSet: TDataSet);
begin
DataSource1.DataSet := Query1;
Query1.AfterOpen := Nil;
//Query1.ResourceOptions.CmdExecMode := amBlocking;
end;
procedure TForm1.Query1BeforeOpen(DataSet: TDataSet);
begin
DataSource1.DataSet := Nil;
end;
end.
显然repeat .. until .. 循环内的代码是无限的,除非有人终止程序。为了在Query1AfterOpen 中执行代码(或改用另一个事件),我缺少什么以便在TFDQuery 完成工作后访问结果集?
【问题讨论】: