idata數據訪問組件庫(RX10.3)版本: 2020-02-20
下載: idata 數據組件庫 for RAD Studio RX10.3.x (260) 發佈於:2020-02-20 使用 bin\dclidata260.bpl 安裝組件
idata 組件是基於 Indy10 開發的, 由服務端作爲中間層服務器,建立客戶端與後臺數據庫的通信。
idata是高效、安全、穩定的數據訪問組件,你可以構建自己的登錄認證系統,同時數據傳輸(SQL指令、參數、數據集)是經過壓縮與動態加密的。
idata的DataSet(數據集組件)是基於內存訪問的高效率組件,移動記錄、數據統計、數據過濾、數據訪問均有優異的體現。
idata是RTL組件,可應用於 Win32、Win64、Linux64、Android、Android64、OSX32、iPad、iPhone 系統的Delphi與C++Builder開發。
類與組件表
場合 |
idata |
名稱 |
說明 |
客 戶 端 |
類 |
TIdField |
內存數據訪問類 |
TIdCustomDataSet |
數據集基類模型 |
||
組件 |
TIdMemDataSet |
內存表組件 |
|
TIdDBConnection |
數據庫連接器組件 |
||
TIdDBQuery |
數據訪問組件 |
||
服 務 端 |
類 |
TIdDBPoolConnector |
池連接器類 |
TIdContextSession |
服務端會話類 |
||
組件 |
TIdDBPoolController |
池控制器組件 |
|
TIdDBPoolMethod |
池方法組件 |
||
TIdDBServer |
服務器組件 |
CSDN_ID: sczyq 聯繫QQ:79896009
TIdField
IdField 是內存數據訪問類, 你可以通過內部記錄索引號快速訪問內部數據。注意:當數據正要編輯(State = dsEdit)並且尚未提交時,訪問到的當前記錄數據是編輯前的。
聲明:
TIdField = class;
TIdField 是內存數據訪問類。
屬性:
屬性 |
說明 |
DataSet: TIdCustomDataSet |
數據集類指針 |
Field: TField |
所關聯的 TField 類 |
DataType: TFieldType |
與 TField 的屬性相同 |
DataSize: Integer |
|
IsBlob: Boolean |
|
IsVirtual : Boolean |
是否來自VirtualFields 的 Field |
IsNull[AIndex: Integer] : Boolean |
識別該記錄的值是否是 NULL |
AsBytes[AIndex: Integer] : TBytes |
將該記錄的值轉換爲相應的數據類型,顧名思義的,不適當的數據轉換可能會產生異常。 |
AsVariant[AIndex: Integer] : Variant |
|
AsString[AIndex: Integer] : String |
|
AsInteger[AIndex: Integer] : Longint |
|
AsBoolean[AIndex: Integer] : Boolean |
|
AsFloat[AIndex: Integer] : Double |
|
AsCurrency[AIndex: Integer] : Currency |
|
AsDateTime[AIndex: Integer] : TDateTime |
|
AsLargeInt[AIndex: Integer] : Largeint |
|
AsSQLTimeStamp[AIndex: Integer] : TSQLTimeStamp |
|
AsCardinal[AIndex: Integer] : Cardinal |
|
AsExtended[AIndex: Integer] : Extended |
|
AsSingle[AIndex: Integer] : Signle |
例如:採用 AsBytes 方法訪問 Blob 字段
Var LStream : TMemoryStream; LBytes : TBytes; begin LStream := TMemoryStream.Create; try // IdDataSet : TIdCustomDataSet LBytes := IdDataSet.IdFieldByName(‘Picture’).AsBytes[IdDataSet.DataIndex]; LStream.Write(LBytes, Length(LBytes)); // Image : TImage Image.Picture.Bitmap.LoadFromStream(LStream); End; finally LStream.Free; end; end; |
TIdCustomDataSet
TIdCustomDataSet 是idata的數據集基類模型。具有以下特點:
- 具有真實Field(SQL)與虛擬Field(VirtualFields)合成一個數據集的功能。
- 數據快速訪問,不必移動數據集記錄即可訪問數據,使用 TIdField 與數據索引號。
- 內部記錄快速過濾器,使用OnFilterData 比使用OnFilterRecord 性能更優秀。
- Blob 數據內存塊採用計數器,減少內存使用量與內存塊創建與釋放。
聲明:
TIdCustomDataSet = class(TDataSet);
屬性:
DataCount: Integer
獲取內部數據總數, 與數據是否過濾 Filtered 無關,
例如: 總記錄100條, 過濾後是80條 |
||
Filtered |
DataCount |
RecordCount |
False |
100 |
100 |
True |
100 |
80 |
快速統計代碼比較:
常規寫法, 記錄訪問模式 |
function TForm1.GetSumValue : Currency; var LField : TField; OldRecNo : Integer; Begin Result := 0; // LIdDataSet : TIdCustomDataSet LField := LIdDataSet.FieldByName(‘Value’); OldRecNo := LIdDataSet.RecNo; try LIdDataSet.DisableControls; LIdDataSet.First; while (not LIdDataSet.Eof) do begin Result := Result + LField.AsCurrency; LIdDataSet.Next; end; finally LIdDataSet.RecNo := OldRecNo; LIdDataSet.EnableControls; end; end; |
idata寫法, 內存數據訪問模式 |
function TForm1.GetSumValue : Currency; var I : Integer; LIdField : TIdField; Begin Result := 0; // LIdDataSet : TIdCustomDataSet LField := LIdDataSet.IdFieldByName(‘Value’);
// 常規寫法, 也是數據未過濾或者全部記錄統計 For I := 0 TO LIdDataSet.DataCount – 1 do Result := Result + LIdField.AsCurrency[I]; { // 如果記錄已經過濾, 只統計已經過濾後的, 就應該這樣寫 For I := 1 TO LIdDataSet.RecordCount do Result := Result + LIdField.AsCurrency[LIdDataSet.DataIndexOf(I)]; } end; |
DataIndex: Integer
獲取當前記錄的數據索引號
LookupOptions: TLookupOptions
使用Lookup 方法時使用的查找選項
ReadOnly: Boolean
數據集是否是隻讀的
Sort: String
進行數據記錄重排序, 允許多字段排序。
表達式格式: 字段名與關鍵字並且關鍵字之間用空格分開, 多個字段之間用分號。
關鍵字,與次序無關 |
說明 |
DESC |
倒序 |
CASE |
大小寫不敏感的, 僅適用於字符數據類型 |
例如: 將Price (價格)作爲從少到大排序,Name (名稱)倒序,並且大小寫不敏感。
Sort := ‘Price;Name DESC CASE’;
VirtualFields: TFieldDefs
始終存在的本地定義的 Field
如果VirtualFields 定義的 Field 名稱與 SQL查詢結果的字段有重名,則數據類型由SQL查詢決定。
例:
VirtualFields 定義 |
||
Name |
DataType |
Size |
NO |
ftAutoInc |
|
TEXT |
ftString |
32 |
SQL字段名與VirtualFields字段名不重疊的結果 |
|||
SQL 查詢 |
SELECT Id, Name, Value FROM TABLE_1 |
||
Name |
DataType |
Size |
說明 |
Id |
ftInteger |
|
類型來自於 TABLE_1 |
Name |
ftWideString |
40 |
|
Value |
ftCurrency |
|
|
NO |
ftAutoInc |
|
類型來自於 VirtualFields 定義 |
TEXT |
ftString |
32 |
SQL字段名與VirtualFields字段名有重疊的結果 |
|||
SQL 查詢 |
SELECT Id AS No, Name, Value FROM TABLE_1 |
||
Name |
DataType |
Size |
說明 |
No |
ftInteger |
|
類型來自於 TABLE_1 |
Name |
ftWideString |
40 |
|
Value |
ftCurrency |
|
|
TEXT |
ftString |
32 |
類型來自 VirtualFields |
VirtualFields 的 Field 類型屬性定義。
ftAutoInc: 初始數據的序號,從1開始,只增不減,即使是中間插入。
數值型:初始數據是0
字符型:初始數據是空
Blob 類型:初始數據是NULL
VirtualFields 定義使數據集操作更加靈活, 程序操作更加方便。
方法:
function IdFieldOf(const AField: TField) : TIdField;
根據字段類獲取 TIdField 類
參數 |
說明 |
AField |
字段類指針 |
function IdFieldByName(const AFieldName: String) : TIdField;
根據字段名獲取 TIdField 類
參數 |
說明 |
AFieldName |
字段名 |
function DataIndexOf(ARecNo : Integer) : Integer;
將記錄號轉換爲數據索引號
參數 |
說明 |
ARecNo |
記錄號 |
function FindDataIndex(const KeyFields: String;
const KeyValues: Variant;
Options: TLocateOptions = []) : Integer;
查找符合條件的首條數據所在的記錄, 返回數據索引號
參數 |
說明 |
|
KeyFields |
字段名列表 |
參照 Locate 方法 |
KeyValues |
值列表 |
|
Options |
查找選項 |
function FindRecNo(const KeyFields: String;
const KeyValues: Variant;
Options: TLocateOptions = []): Integer;
查找符合條件的首條數據所在的記錄, 返回記錄號
參數 |
說明 |
|
KeyFields |
字段名列表 |
參照 Locate 方法 |
KeyValues |
值列表 |
|
Options |
查找選項 |
procedure SaveToStream(AStream: TStream;
AExcludeVirtual : Boolean = False);
保存數據到idata數據格式流, 與記錄是否過濾相關
參數 |
說明 |
AStream |
目標流,必須已經初始化 |
AExcludeVirtual |
是否排除由VirtualFields 產生的字段 |
procedure SaveToFile(AFileName: String;
AExcludeVirtual : Boolean = False);
保存數據到idata數據格式文件, 與記錄是否過濾相關
參數 |
說明 |
AFileName |
文件名,建議包括完成路徑 |
AExcludeVirtual |
是否排除由VirtualFields 產生的字段 |
事件:
OnFilterData : TIdFilterDataEvent 記錄過濾器事件
與 OnFilterRecord 過濾器事件作用相同,但OnFilterRecord 事件優先,只有不存在OnFilterRecord 事件的情況下,纔會使用OnFilterData 事件。
但是,OnFilterRecord 事件是記錄型的,DataSet在執行過濾時,需要移動記錄號。而OnFilterData 是內存數據型的,執行過濾時,不會移動記錄號,因此具有更高的效率。
OnFilterRecord 與 OnFilterData的代碼比較:
OnFilterRecord 記錄訪問過濾模式 |
procrdure TForm1.IdDBQuery1FilterRecord(DataSet: TDataSet; var Accept: Boolean); begin // 執行到這裏時,DataSet 會移動記錄號,以當前記錄訪問緩衝區數據 Accept := IdDBQuery1.FieldByName(‘Value’).AsCurrency > 100; end; |
OnFilterData 內存數據訪問過濾模式 |
procrdure TForm1.IdDBQuery1FilterData(DataSet: TDataSet; const Index : Integer; var Accept: Boolean); begin // 執行到這裏時,DataSet 不會移動記錄號,使用Index去直接訪問內存數據 Accept := IdDBQuery1.IdFieldByName(‘Value’). AsCurrency[Index] > 100; end; |
討論: 爲什麼內存數據訪問會比記錄訪問效率更高?
內存數據訪問, 是直接從內存中提取數據, 原理是: DATA -> VALUE
記錄訪問, 是間接的通過緩存提取數據, 原理是:DATA -> BUFFER -> VALUE 即:每一次移動記錄, 都會將當前內存記錄複製到緩存區, 然後再從緩存中提取值,而且DataSet每一次移動記錄(即使DisableControls), 都需要執行一批相應的指令,因而影響了效率。
TIdMemDataSet
TIdMemDataSet 是內存表組件。
聲明:
TIdMemDataSet = class(TIdCustomDataSet);
方法:
procedure CreateDataSet;
創建由VirtualFields 定義的字段並且打開空數據集
procedure CreateFieldsFromDataSet(ADataSet: TDataSet);
創建由源數據集相同的字段並且打開空數據集,如果存在VirtualFields 定義的字段並且字段名稱未重疊,能夠一併創建。源數據集的記錄不會複製過來。
參數 |
說明 |
ADataSet |
源數據集 |
procedure AddRecordsFromDataSet(ADataSet: TDataSet);
追加源數據集的記錄到當前數據集,字段名或數據類型不相同的數據會被拋棄,使用該方法前,數據集必須是活動的。
參數 |
說明 |
ADataSet |
源數據集 |
procedure LoadFromDataSet(ADataSet: TDataSet);
裝載源數據集的數據到當前數據集,該方法的作用就是執行 CreateFieldsFromDataSet和 AddRecordsFromDataSet。
參數 |
說明 |
ADataSet |
源數據集 |
procedure LoadFromStream(AStream: TStream);
從idata數據格式流中裝載數據到當前數據集,如果存在VirtualFields 定義的字段並且字段名稱未重疊,能夠一併創建。
參數 |
說明 |
AStream |
目標流,是使用 SaveToStream 導出的 |
procedure LoadFromFile(AFileName: String);
從idata數據格式文件中裝載數據到當前數據集, 如果存在VirtualFields 定義的字段並且字段名稱未重疊,能夠一併創建。
參數 |
說明 |
AFileName |
idata數據格式文件名,建議使用完整路徑 |
procedure EmptyDataSet; 清空數據。
TIdDBConnection
TIdCustomDBConnection 是idata的數據庫通訊類模型。TIdDBConnection 是idata的數據庫通訊組件。是建立與服務端(TIdDBServer)的交互的必須工具。具有以下特點:
- 自動斷線重連功能,即使當前的網絡環境已經改變。
- 線程安全,不同線程間與服務端數據的交互自動採用安全鎖。
- 直接執行SQL語句(ExecuteSQL),或將SQL數據集導出到數據集流(QueryToStream, idata數據流格式)。
- 與TIdDBServer結合,可以自定義的用戶登錄校驗方式。
聲明:
TIdCustomDBConnection = class(TCustomConnection);
TIdDBConnection = class(TIdCustomDBConnection);
屬性:
Server : String
服務器的主機地址,可以是域名。
如果服務器端口號不是默認端口是698,那麼在主機後加上端口號。格式是:<主機>[:<端口>]
IP版本 |
主機 |
端口 |
值 |
IPv4 |
192.168.1.100 |
698 |
192.168.1.100 |
3333 |
192.168.1.100:3333 |
||
IPv6 |
[1::1] |
698 |
[1::1] |
3333 |
[1::1]:3333 |
IPVersion : TIdIPVersion
連接服務器採用的IP協議,默認是IPv4。
ReuseSocket : TIdReuseSocket
服務器是否重用連接。
Username : String
登錄服務器的用戶名,是否需要決定於服務器。
Password : String
登錄服務器的口令,是否需要決定於服務器。
BlockSize : Word
數據通信的每個塊最少值,單位是KB,默認值是512KB,該值在大數據量的情況下,起作用。
值 |
響應速度 |
通信次數 |
變大 |
劣 |
優 |
變小 |
優 |
劣 |
CommandTimeout : Word
命令執行超時等待時間,單位是秒,當向服務器發送SQL指令後,如果超過這個等待時間無響應,視爲超時,並拋出異常(有些情況是實際是執行成功了的, 只是執行時間過長而已)。
ConnectionTimeout : Word
連接服務器的超時等待時間,單位是秒,當準備向服務器連接後,如果超過這個等待時間無響應,視爲超時,並拋出異常。
Identity : Largeint
服務器與客戶端通信的唯一的連接碼,每次連接服務器都會分配一個不同的連接碼,該屬性是隻讀的。
DBProduct : String
服務器端後臺數據庫產品名稱,客戶獲取該數據庫產品名稱的作用,主要是用於客戶端開發時編寫SQL語句時,可以根據該屬性編碼不同的SQL指令。
事件:
OnLock : TNotifyEvent
當鎖定Socket時發生該事件,一般情況下是在開始執行SQL前。
OnUnlock : TNotifyEvent
當解鎖Socket時發生該事件,一般情況下是執行SQL並已經完成後。
TIdDBMakeUserInfo = procedure (const AParams : TParams);
OnMakeUserInfo : TIdDBMakeUserInfo
連接服務器時發生該事件。需要提供哪些參數由服務器決定,如果沒有編寫相應的事件,系統會自動加入 Username 與 Password 到這個參數列表。
參數 |
說明 |
AParams |
客戶端登錄參數表 |
TIdDBSQLAction = (saOpen, saAppend, saUpdate, saDelete, saExecute);
TIdDBSQLExceptionEvent = procedure (Sender: TObject; SQL : TStrings;
const Action : TIdDBSQLAction; E: Exception);
OnSQLException : TIdDBSQLExceptionEvent
當SQL發生異常時發生該事件。
參數 |
說明 |
Sender |
產生異常的組件類 |
SQL |
SQL 語句列表 |
Action |
當前的動作 |
E |
異常類 |
OnConnected : TNotifyEvent
當連接成功時發生該事件。
OnDisconnected : TNotifyEvent
當斷開連接時發生該事件。
方法:
Host : String 獲取服務器的主機地址
Port : String 獲取服務器的端口
procedure Lock; 鎖定 Socket
procedure Unlock; 解鎖 Socket。
鎖定與解鎖是配套的,建議使用 try … finally … end 異常。
try Lock; … finally Unlock end; |
在使用TIdDBQuery執行SQL指令或時,能夠自動鎖定與解鎖,你無需編寫這些鎖定與解鎖的代碼Socket。只有在使用Socket執行擴展的協議時,才需要用到Lock 和 Unlock。
Procedure QueryToStream(AStream : TStream, ASQL : String ASQL);
執行查詢SQL指令,將結果輸出到流。
參數 |
說明 |
AStream |
目標流,指針必須初始化 |
ASQL |
SQL指令 |
Procedure QueryToStream(AStream : TStream; ASQL : TStrings ASQL, AParams : AParams = nil);
執行查詢SQL指令,將結果輸出到流。
參數 |
說明 |
AStream |
目標流,指針必須初始化 |
ASQL |
多行SQL指令表 |
AParams |
與SQL指令表對應的參數,無參數可省略 |
function ExecuteSQL(ASQL : String) : Integer;
執行SQL指令,返回少於0則表示失敗的。執行時自動加鎖與解鎖Socket。
參數 |
說明 |
ASQL |
SQL指令 |
function ExecuteSQL(ASQL : TStrings; AParams: TParams = nil) : Integer;
執行SQL指令,返回少於0則表示失敗的。執行時自動加鎖與解鎖Socket。
參數 |
說明 |
AStrings |
多行SQL指令表 |
AParams |
與SQL指令表對應的參數,無參數可省略 |
function BeginTrans : Integer; 啓動事務, 啓動前自動鎖定Socket。
function CommitTrans : Boolean; 提交事務,執行成功自動解鎖Socket。
function RollbackTrans : Boolean; 回滾事務,執行成功自動解鎖Socket。
建議使用 try … exception … end 異常處理。
try BeginTrans; … CommitTrans; exception RollbackTrans; end; |
TIdDBQuery
TIdDBQuery 是SQL數據訪問組件。具有以下特點。
- 可以定義數據集是本地內存方式或連線方式,即數據修改後是否要提交到服務端。
- 當網絡環境改變時(TIdDBConnection斷線時),數據集不會被關閉。當準備將編輯數據提交到服務器時,TIdDBConnection 會重連。
- TIdDBCustomDataSet 所具有的特點。
4. 即使屬性 LocalEditor = False ,由 VirtualFields 定義而產生的字段,數據修改後,總是不會提交到遠程服務器。
聲明:
TIdDBQuery = class(TIdCustomDataSet);
屬性:
property Connection : TIdCustomDBConnection
遠程SQL數據連接器。
property SQL : TStrings
SQL指令。
property Params : TParams
SQL指令內包含的參數列表。
property LocalEditor : Boolean
決定數據編輯器是否是本地的。這個值必須是數據集在關閉的狀態時才能改變。
如果這個值爲 True,那麼,這個 TIdDBQuery 就是一個內存表,數據編輯後不會提交到SQL服務器。
如是果這個值爲 False(默認),那麼,當發生數據編輯提交,記錄刪除等操作, 同步提交到SQL服務器,並且必須成功, 否則產生異常。
方法:
procedure OpenSQL(ASQL : String);
打開由參數指令決定的數據。
參數 |
說明 |
ASQL |
SQL指令 |
這個方法只是簡化了代碼編寫, 與Open 不同點在於,Open 方法必須先定義屬性SQL指令,然後才能Open。
如果存在VirtualFields 定義的字段並且字段名稱與SQL返回結果未重疊,能夠一併創建, 具體內容請見 TIdCustomDataSet 的屬性VirtualFields 說明。
function ExecSQL(ASQL : String = ‘’); : Integer;
執行SQL。
參數 |
說明 |
ASQL |
SQL指令,如果空指令由執行屬性SQL定義的指令 |
這個方法也是簡化了代碼編寫,但如果參數存在SQL指令,則不會改變屬性SQL的定義。
事件:
property OnFetchProgress : TDataSetNotifyEvent
當SQL連接器獲取到一個數據塊,並處理完該數據塊時產生該事件,SQL獲取數據可能由多個數據塊組成。得到該事件表示SQL正在處理。
property OnFetchComplete : TDataSetNotifyEvent
當SQL獲取並處理完全部數據塊時產生該事件,得到該事件表示SQL已經完成。
TIdDBPoolConnector
池連接器類,你要通過控制器的方法獲取並回收,而不是創建與刪除。
聲明:
TIdDBPoolConnector = class(TComponent);
屬性:
property Controller : TIdDBPoolController;
池控制器。
property Connection : TCustomConnection;
源數據庫連接,來自池初始化方法 DoInitialize。
property DataSet : TDataSet;
數據集,一般是Query組件,來自池初始化方法 DoInitialize。
property SQL : TStrings;
SQL指令。
property Params : TParams;
SQL指令內包含的參數列表。
property Activity : TDataTime
當前連接器最後活動的時間。
方法:
procedure Clear;
清空SQL指令與參數, 並關閉DataSet數據集。
procedure CloseSQL;
關閉數據集, 如何做決定於池方法 DoCloseSQL。
procedure OpenSQL;
打開由參數指令決定的數據, 如何做決定於池方法 DoOpenSQL。
procedure ExecSQL;
執行由參數指令決定的數據, 如何做決定於池方法 DoExecSQL。
procedure BeginTrans;
啓動一個數據庫事務, 如何做決定於池方法 DoBeginTrans。
procedure CommitTrans;
提交當前數據庫事務, 如何做決定於池方法 DoCommitTrans。
procedure RollbackTrans;
回滾當前數據庫事務, 如何做決定於池方法 DoRollbackTrans。
TIdContextSession
服務器會話類與協議庫。你無需創建該類,在一些服務器事件中會用到這個類。
聲明:
TIdContextSession = class(TIdServerContext);
屬性:
Connector : TIdDBPoolConnector;
源數據庫連接池連接器。
Identity : Largeint;
當前會話種子。
Username : String;
用戶名。
BlockSize : Word;
數據傳送塊大少,參照 TIdDBConnection.BlockSize 屬性。
LoginTime : TDateTime;
登錄時間。
property Activity : TDataTime
當前連接最後活動的時間。
TIdDBPoolMethod
源數據庫連接池控制器方法。編寫這些事件過程,決定於你採用哪種源數據庫連接方式(BDE/ADO/FireDAC/DBX/...)。
聲明:
TIdCustomDBPoolMethod = class(TComponent)
TIdDBPoolMethod = class(TIdCustomDBPoolMethod)
事件:
TDBConnectorInitialize = procedure(AOwner : TComponent;
var AConnection : TCustomConnection; var ADataSet : TDataSet) of object;
OnInitialize: TIdDBPoolConnectorInitialize;
初始化池連接器組件事件,你必須創建池連接器的 AConnection 與 ADataSet 組件。
參數 |
說明 |
AOwner |
創建池連接器組件的屬主 |
AConnection |
源數據庫連接組件 |
ADataSet |
數據集的指針 |
OnCloseSQL: TIdDBPoolConnectorMetdod;
關閉數據集時啓動該事件。
OnOpenSQL: TIdDBPoolConnectorMetdod;
打開SQL指令時啓動該事件。
OnExecSQL: TIdDBPoolConnectorMetdod;
執行SQL指令時啓動該事件。
OnBeginTrans: TIdDBPoolConnectorMetdod;
開始一個數據庫事務時啓動該事件。
OnCommitTrans: TIdDBPoolConnectorMetdod;
提交當前數據庫事務時啓動該事件。
OnRollbackTrans: TIdDBPoolConnectorMetdod;
回滾當前數據庫事務時啓動該事件。
討論:
你也可以通過繼承TIdCustomDBPoolMethod 的類來提供給池控制器,而不採用TIdDBPoolMethod 組件方法。
例如:採用 ADO 方式連接源數據庫的方法類 ADOPoolMethod.pas
unit ADOPoolMethod;
{ 本代碼配合數據庫連接池組件使用, 僅適用於 ADO 環境 使用本代碼後, 你就無需再編寫 TIdDBPoolMethod 的事件處理過程. 只需要將這個 Pas 加入到你的工程, 然後創建該TADODBPoolMethod類給控制器 IdDBPoolController1.PoolMethod := TADODBPoolMethod.Create(Self, ConnStr); 由於 ADO 是 Windows 的 COM 組件, 而連接池初始化是在線程中完成的 所以你必須編寫 TDBPoolController 組件的 OnBeforeRun 與 OnAfterRun 事件方法 進行 COM 的初始化與回收 procedure TMyServer.IdDBPoolController1BeforeRun(ASender : TObject); begin CoInitialize(nil); end; procedure TMyServer.IdDBPoolController1AfterRun(ASender : TObject); begin CoUninitialize(); end; }
interface
uses System.Classes, Data.DB, idata.Pool, Data.Win.ADODB;
type TADODBPoolMethod = class(TIdCustomDBPoolMethod) private FConnectionString : String; function GetQuery(AConnector : TIdDBPoolConnector) : TADOQuery; protected procedure DoInitialize(AConnector : TIdDBPoolConnector; var AConnection : TCustomConnection; var ADataSet : TDataSet); override; procedure DoCloseSQL(AConnector : TIdDBPoolConnector); override; procedure DoOpenSQL(AConnector : TIdDBPoolConnector); override; procedure DoExecSQL(AConnector : TIdDBPoolConnector); override; procedure DoBeginTrans(AConnector : TIdDBPoolConnector); override; procedure DoCommitTrans(AConnector : TIdDBPoolConnector); override; procedure DoRollbackTrans(AConnector : TIdDBPoolConnector); override; public constructor Create(AOwner : TComponent; AConnectionString : String); reintrodce; end;
implementation
constructor TADODBPoolMethod.Create(AOwner : TComponent; AConnectionString : String); begin inherited Create(AOwner); FConnectionString := AConnectionString; end;
function TADODBPoolMethod.GetQuery(AConnector :TIdDBPoolConnector) :TADOQuery; var I : Integer; LParam : TParam; LParameter : TParameter; begin Result := TADOQuery(AConnector.DataSet); Result.Close; Result.SQL.Clear; Result.SQL.Assign(AConnector.SQL); for I := 0 to AConnector.Params.Count - 1 do begin LParam := AConnector.Params[I];
LParameter := Result.Parameters.FindParam(LParam.Name); if not Assigned(LParameter) then LParameter := Result.Parameters.AddParameter;
LParameter.Assign(LParam); end; end;
procedure TADODBPoolMethod.DoInitialize(AConnector : TIdDBPoolConnector; var AConnection : TCustomConnection; var ADataSet : TDataSet); begin AConnection := TADOConnection.Create(AConnector); TADOConnection(AConnection).ConnectionString := FConnectionString; AConnection.LoginPrompt := False;
ADataSet := TADOQuery.Create(AConnector); TADOQuery(ADataSet).Connection := TADOConnection(AConnection); end;
procedure TADODBPoolMethod.DoCloseSQL(AConnector : TIdDBPoolConnector); var LQuery : TADOQuery; begin LQuery := TADOQuery(AConnector.DataSet); LQuery.Close; LQuery.SQL.Clear; end;
procedure TADODBPoolMethod.DoOpenSQL(AConnector : TIdDBPoolConnector); begin GetQuery(AConnector).Open; end;
procedure TADODBPoolMethod.DoExecSQL(AConnector : TIdDBPoolConnector); begin GetQuery(AConnector).ExecSQL; end;
procedure TADODBPoolMethod.DoBeginTrans(AConnector : TIdDBPoolConnector); begin TADOConnection(AConnector.Connection).BeginTrans; end;
procedure TADODBPoolMethod.DoCommitTrans(AConnector : TIdDBPoolConnector); begin TADOConnection(AConnector.Connection).CommitTrans; end;
procedure TADODBPoolMethod.DoRollbackTrans(AConnector : TIdDBPoolConnector); begin TADOConnection(AConnector.Connection).RollbackTrans; end;
end. |
TIdDBPoolController
源數據庫連接池控制器。
聲明:
TIdDBPoolController= class(TComponent);
屬性:
Active : Boolean;
池控制器是否在開啓狀態。
PoolCount : Integer;
當前池連接器計數。
AlwaysCount : Word;
充許保持連接器的數量。當池控制器開啓後,並不會立刻創建這個數量的連接器(TIdDBPoolConnector),當連接器數達到這個量時,這些連接器會一直保持,直到池控制器關閉。連接器數超過這個量時,多餘的會被釋放掉。
IdlenessTimeout : Word;
當某個連接器空閒了這個時間(秒)後,並且連接器總數多於充許保持數時自動釋放掉。
PoolMethod : TIdCustomDBPoolMethod;
連接器方法。
方法:
function Acquire(ASession : TObject) : TIdDBPoolConnector;
獲取一個連接器。
procedure Recovery(AConnector : TIdDBPoolConnector);
回收一個連接器。
事件:
AfterRun : TNotifyEvent;
完成後事件,適用於Windows 系統釋放線程COM。
BeforeRun : TNotifyEvent;
啓動時的事件,適用於Windows 系統初始化線程COM。
OnPoolChanged : TNotifyEvent;
連接器的數量改變時啓動該事件。
OnSQLException : TDBSQLExceptionEvent;
當SQL發生異常時發生該事件。
TIdDBServer
數據庫服務器組件。是提供客戶端與Database的數據交互中間件。
聲明:
TIdCustomDBServer = class(TIdCustomTCPServer);
TIdDBServer = class(TIdCustomDBServer);
屬性: (由 Indy10 的 TIdCustomTCPServer 提供的屬性、方法、事件不再列出。)
DBController : TIdDBPoolController;
源數據庫連接池控制器。
DBProduct : String;
源數據庫產品標識, 參照 TIdDBConnection.DBProduct 屬性。
LoginTimeout : Word;
客戶端登錄超時設置(秒)。
TransactionTimeout: Word;
事務超時設置(秒)。
InactiveTimeout: Word;
客戶端會話超時設置(秒),某個連接在這個時間內無會話的即被判定爲超時並斷開這個他。
事件:
OnAfterRun : TNotifyEvent;
完成後事件,適用於Windows 系統釋放線程COM。
OnBeforeRun : TNotifyEvent;
啓動時的事件,適用於Windows 系統初始化線程COM。
TIdDBLoginVerifyMethod = procedure(ASession : TIdContextSession;
AParams : TParams; var AStatus: Boolean) of object;;
OnLoginVerify : TIdDBLoginVerifyMethod;
客戶端登錄時使用該事件,該事件內定義了客戶端登錄所需提供的參數,根據這些參數判定登錄是否成功。
參數 |
說明 |
ASession |
客戶端會話類,你可以通過這個類去獲取池連接器 |
AParams |
客戶端提供的登錄參數表 |
AStatus |
返回值,登錄成功時置爲 True |
如果沒有寫該事件過程,登錄總是成功的(匿名的)。
該事件決定了客戶端登錄事件的編寫方式, 參見 TIdDBConnection.OnMakeUserInfo 事件說明。
OnExtendProtocol : TIdDBExtendProtocolMethod;
服務端擴展協議,當客戶端發送了無法識別的協議時,觸發該事件,目前是保留的。
TIdDBGetPrimaryKeyMethod = procedure(ASession : TIdContextSession;
const ATableName : String; var AFieldNames : String) of object;
OnGetPrimaryKey : TIdDBGetPrimaryKeyMethod;
獲取表主鍵字段的事件。不同的數據庫產品獲取表主鍵的方式不相同,主鍵主要應用在TIdDBQuery 數據提交時使用。
參數 |
說明 |
ASession |
客戶端會話類,你可以通過這個類去獲取池連接器 |
ATableName |
表名 |
AFieldNames |
返回字段列表,每個字段後加上半角分號 |