1. 程式人生 > >多線程數據庫查詢(ADO)

多線程數據庫查詢(ADO)

eof field mos variant conn query ati button 建立

ADO多線程數據庫查詢通常會出現3個問題:

1、CoInitialize 沒有調用(CoInitialize was not called);所以,在使用任何dbGo對象前,必須手 調用CoInitialize和CoUninitialize。調用CoInitialize失敗會產生"CoInitialize was not called"例外。

2、畫布不允許繪畫(Canvas does not allow drawing);所以,必須通過Synchronize過程來通知主線程訪問主窗體上的任何控件。

3、不能使用主ADO連接(Main TADoConnection cannot be used!);所以,線程中不能使用主線程中TADOConnection對象,每個線程必須創建自己的數據庫連接。

Delphi2007安裝後在X:/Program Files/Common Files/CodeGear Shared/Data目錄下有一個dbdemos.mdb文件,用來作為測試的例子。dbdemos.mdb中的customer表保存了客戶信息,orders表中保存了訂單信息。

測試程序流程大致是這樣的:在主窗體上放TADOConnection和TQuery控件,啟動時這個TQuery從Customer表中查出客戶編碼CustNo和公司名稱Company,放到三個Combox框中,分別在三個列表框中選定客戶公司名稱,按照公司名稱所對應的客戶代碼建立三個線程同時在orders表中查詢銷售日期SaleDate分別填入ListBox中。

unit ADOThread;  
   
interface  
   
uses  
  Classes,StdCtrls,ADODB;  
   
type  
  TADOThread = class(TThread)  
  private  
    { Private declarations }  
    FListBox:TListBox;  
    FLabel:TLabel;  
    ConnString:WideString;  
    FSQLString:string;  
    procedure UpdateCount;  
  protected  
    procedure Execute; override;  
  public  
    constructor Create(SQL:string;LB:TListBox;Lab:TLabel);  
  end;  
   
implementation  
   
uses Main,SysUtils,ActiveX;  
   
{ TADOThread }  
   
constructor TADOThread.Create(SQL: string; LB: TListBox;Lab:TLabel);  
begin  
  ConnString:=Form2.ADOConnection1.ConnectionString;  
  FListBox:=LB;  
  FLabel:=Lab;  
  FSQLString:=SQL;  
  Inherited Create(False);  
end;  
   
procedure TADOThread.Execute;  
var  
  Qry:TADOQuery;  
  i:Integer;  
begin  
  { Place thread code here }  
  FreeOnTerminate:=True;  
  CoInitialize(nil);  //必須調用(需Uses ActiveX)   
  Qry:=TADOQuery.Create(nil);  
  try  
    Qry.ConnectionString:=ConnString;   //必須有自己的連接   
    Qry.Close;  
    Qry.SQL.Clear;  
    Qry.SQL.Add(FSQLString);  
    Qry.Open;  
    FListBox.Clear;  
    for i := 0 to 100 do  //為了執行久點重復歷遍數據集101次   
      begin  
        while not Qry.Eof And not Terminated do  
        begin  
          FListBox.AddItem(Qry.Fields[0].asstring,nil);  
          //如果不調用Synchronize,會出現Canvas Does NOT Allow Drawing   
          Synchronize(UpdateCount);  
          Qry.Next;  
        end;  
        Qry.First;  
        FListBox.AddItem(‘*******‘,nil);  
      end;  
  finally  
    Qry.Free;  
  end;  
  CoUninitialize;  
end;  
   
procedure TADOThread.UpdateCount;  
begin  
  FLabel.Caption:=IntToStr(FListBox.Items.Count);  
end;  
   
end.  

  

unit Main;  
   
interface  
   
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  Dialogs, DB, ADODB, StdCtrls;  
   
type  
  TForm2 = class(TForm)  
    ComboBox1: TComboBox;  
    ComboBox2: TComboBox;  
    ComboBox3: TComboBox;  
    ListBox1: TListBox;  
    ListBox2: TListBox;  
    ListBox3: TListBox;  
    Button1: TButton;  
    ADOConnection1: TADOConnection;  
    ADOQuery1: TADOQuery;  
    Label1: TLabel;  
    Label2: TLabel;  
    Label3: TLabel;  
    procedure FormCreate(Sender: TObject);  
    procedure Button1Click(Sender: TObject);  
  private  
    { Private declarations }  
  public  
    { Public declarations }  
  end;  
   
var  
  Form2: TForm2;  
   
implementation  
   
uses ADOThread;  
   
{$R *.dfm}  
   
procedure TForm2.Button1Click(Sender: TObject);  
const  
  SQL_CONST=‘Select SaleDate from orders where CustNo = %d‘;  
var  
  c1,c2,c3:Integer;  
  s1,s2,s3:string;  
begin  
  //取得三個選擇框客戶的編碼   
  c1:=Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);  
  c2:=Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]);  
  c3:=Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]);  
  //生成SQL 查詢語句   
  s1:=Format(SQL_CONST,[c1]);  
  s2:=Format(SQL_CONST,[c2]);  
  s3:=Format(SQL_CONST,[c3]);  
  //三個線程同時查詢   
  TADOThread.Create(s1,ListBox1,Label1);  
  TADOThread.Create(s2,ListBox2,Label2);  
  TADOThread.Create(s3,ListBox3,Label3);  
end;  

procedure TForm2.FormCreate(Sender: TObject);  
var  
  strSQL:string;  
begin  
  strSQL:=‘SELECT CustNo,Company FROM customer‘;  
  ADOQuery1.Close;  
  ADOQuery1.SQL.Clear;  
  ADOQuery1.SQL.Add(strSQL);  
  ADOQuery1.Open;  
  ComboBox1.Clear;  
  ComboBox2.Clear;  
  ComboBox3.Clear;  
  //將客戶Company和相關CustNo填到ComboBox中   
  while not ADOQuery1.Eof do  
  begin  
    ComboBox1.AddItem(ADOQuery1.Fields[1].asString,  
        TObject(ADOQuery1.Fields[0].AsInteger));  
    ADOQuery1.Next;  
  end;  
  ComboBox2.Items.Assign(ComboBox1.Items);  
  ComboBox3.Items.Assign(ComboBox1.Items);  
  // 默認選中第一個   
  ComboBox1.ItemIndex := 0;  
  ComboBox2.ItemIndex := 0;  
  ComboBox3.ItemIndex := 0;  
end;  

end.{ADO查詢多線程單元}  

  

多線程數據庫查詢(ADO)