螺纹德尔福ADO查询

螺纹德尔福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; 
+0

为什么你想要一个线程?如果您只是想在查询运行时执行其他操作,则可以使用异步查询(无论如何,它都会在另一个线程上运行查询)。 – Rob 2013-04-27 11:41:12

+0

嗨罗布,感谢您的建议。但是我读过一些地方,很多用户在使用异步查询时遇到了句柄和内存泄漏问题。 – 2013-04-28 01:00:30

+0

我还没有看到。我有自主的(Delphi)软件,每次运行数周,不断进行异步ADO查询。我有一些其他的C++代码,可以在运行时定期处理100000000个异步查询。 – Rob 2013-04-28 11:05:48

可重用性。
每个线程创建一个拥有自己的连接的自己的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. 
+0

@kobik谢谢,一种过度的.. – bummi 2013-04-28 10:24:58

+0

@bummi,感谢这个代码示例,我会在我的项目中尝试这个。 – 2013-04-30 02:44:06