螺纹德尔福ADO查询
我有一个查询代码,我可以调用每次我需要从数据库中获取数据,我希望它是线程。不知道如何在一个线程中实现这个,所以我可以重用这段代码,基本上,我希望这个代码在一个线程中。我知道如何在线程内部创建一个简单的数据库查询,但想要可重用的东西。任何人都可以指出我在哪里可以找到这方面的例子,或者足够提供一个例子吗?螺纹德尔福ADO查询
这里是我的示例数据库查询:
function TDBConnection.SQLOpen(const SQLStr: String): TDataSet;
var
i: Integer
begin
try
Result := TADOQuery.Create(DBConnect.FDatabaseConection);
TADOQuery(Result).Connection:=DBConnect.FDatabaseConnection;
TADOQuery(Result).CommandTimeOut:=30;
TADOQuery(Result).SQL.Text := SQLStr;
TADOQuery(Result).Open;
except
end;
end;
这是我如何调用上述功能的示例:使用带parameterinformations数组
function TDBConnection.GetUserInfo: Boolean;
var
sqlStr: String;
Database: TDataset;
begin
sqlStr:= 'SELECT FIELD1, FIELD2, FIELD3 FROM TABLE1';
try
Dataset := SQLOpen(sqlStr);
if not Dataset.IsEmpty then
begin
//pass result to StringGrid
end;
finally
FreeAndNil(SQLParams);
FreeAndNil(Dataset);
end;
end;
可重用性。
每个线程创建一个拥有自己的连接的自己的Adodataset。
记录集可用于线程终止后的显示和编辑。
对于真正的应用程序,处理线程实例将不得不被添加。
unit ThreadedAdoDataset;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, ADODB, Grids, DBGrids;
type
TFieldInfoRecord = Record // as far as sometimes parametertypes can not be detected by
DataType: TFieldType; // Ado on his own, provide all needed informations
Name: String;
Size: Integer;
Value: Variant;
End;
TFieldInfoArray = Array of TFieldInfoRecord;
TDBThread = Class(TThread)
Constructor Create(Const ConnectionString, SQL: String;
FDArray: TFieldInfoArray);
private
FConnectionString, FSQL: String;
FFDArray: TFieldInfoArray;
FRecordSet: _RecordSet;
Protected
Procedure Execute; override;
public
Property RecordSet: _RecordSet read FRecordSet;
End;
TForm7 = class(TForm)
ADOConnection1: TADOConnection;
Button1: TButton;
ADODataSet1: TADODataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
procedure ThreadTerminate(Sender: TObject);
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form7: TForm7;
implementation
uses ActiveX;
{$R *.dfm}
procedure TForm7.Button1Click(Sender: TObject);
var
FDArray: TFieldInfoArray;
I: Integer;
begin
// prepare parameterinformations
SetLength(FDArray, 1);
FDArray[0].Name := 'cn';
FDArray[0].DataType := ftString;
FDArray[0].Size := 20;
FDArray[0].Value := '%ue%';
for I := 0 to 10 do // testrun with 11 threads
With TDBThread.Create(ADOConnection1.ConnectionString,
'select * from Composition where Componame like :cn', FDArray) do
begin
FreeOnTerminate := true;
// assign the wished procedure to ba called on terminate
OnTerminate := ThreadTerminate;
end;
end;
procedure TForm7.ThreadTerminate(Sender: TObject);
begin
// example of assigning the recordset of the thread for displaying and editing
// NOTE for editing the connection of ADODataSet1 has to be fitting to the threadcall
ADODataSet1.RecordSet := TDBThread(Sender).RecordSet;
end;
procedure TForm7.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutDown := true;
end;
{ TDBThread }
constructor TDBThread.Create(const ConnectionString, SQL: String;
FDArray: TFieldInfoArray);
var
I: Integer;
begin
inherited Create(false);
FConnectionString := ConnectionString;
FSQL := SQL;
SetLength(FFDArray, Length(FDArray));
for I := 0 to High(FDArray) do
begin
FFDArray[I].DataType := FDArray[I].DataType;
FFDArray[I].Size := FDArray[I].Size;
FFDArray[I].Name := FDArray[I].Name;
FFDArray[I].Value := FDArray[I].Value;
end;
end;
procedure TDBThread.Execute;
var
I: Integer;
begin
inherited;
CoInitialize(nil);
try
With TADODataSet.Create(nil) do
try
CommandTimeOut := 600;
ConnectionString := FConnectionString;
// use own connection for the dataset
// will requite a conncetionsstring including all
// information for loggon
Commandtext := FSQL;
Parameters.ParseSQL(FSQL, true); // extract parameters
for I := Low(FFDArray) to High(FFDArray) do // set parametervalues
begin
Parameters.ParamByName(FFDArray[I].Name).DataType := FFDArray[I]
.DataType;
Parameters.ParamByName(FFDArray[I].Name).Size := FFDArray[I].Size;
Parameters.ParamByName(FFDArray[I].Name).Value := FFDArray[I].Value;
end;
Open;
FRecordSet := RecordSet; // keep recordset
finally
Free;
end;
finally
CoUnInitialize;
end;
end;
end.
@kobik谢谢,一种过度的.. – bummi 2013-04-28 10:24:58
@bummi,感谢这个代码示例,我会在我的项目中尝试这个。 – 2013-04-30 02:44:06
为什么你想要一个线程?如果您只是想在查询运行时执行其他操作,则可以使用异步查询(无论如何,它都会在另一个线程上运行查询)。 – Rob 2013-04-27 11:41:12
嗨罗布,感谢您的建议。但是我读过一些地方,很多用户在使用异步查询时遇到了句柄和内存泄漏问题。 – 2013-04-28 01:00:30
我还没有看到。我有自主的(Delphi)软件,每次运行数周,不断进行异步ADO查询。我有一些其他的C++代码,可以在运行时定期处理100000000个异步查询。 – Rob 2013-04-28 11:05:48