TManagedDataSet和DataSetPool的實現 (轉)
TManagedDataSet和DataSetPool的實現:namespace prefix = o ns = "urn:schemas--com::office" />
天天用,自己有了很多想法。寫程式碼之餘,有空閒時間就把一些東西整理成文件。
Delphi中使用最多的大概是AdoExpress,這是Borland封裝了Microsoft的Ado的東東,使用頻率最多的TAdoDataSet對應了Ado原生的RecordSet,在功能上做了一些增強,但用法基本一致,用多了就感覺TAdoDataSet還有擴充和改造的地方。
由於程式碼中使用了很多的TAdoDataSet,建立和釋放非常頻繁,而且每次建立後都要設定很多基本相同的屬性,頗為麻煩。於是想到可以實現一個記錄集池,每次當需要一個記錄集時,從這個池中得到一個空閒且符合要求的(只讀或可讀寫),用完了就被池回收,如果池中記錄集不夠,就自動生成新的記錄集物件。
首先要做的是改造TAdoDataSet,我寫了一個TManagedDataSet,繼承自TAdoDataSet,可以自己知道自己是被人使用還是空閒(透過IsUsed()),重寫了Free(),把本來釋放的動作改為僅是把自己設定為空閒,並清除狀態(Session)資訊,並可以透過()返回一個指向自己的TDataSource物件。
有了這些基礎後,就可以很快的構建TDataSetPool類了,這個類僅是儲存可用的TManagedDataSet物件,透過GetDataSet(WantType : TManagedDataSetType)返回一個空閒的資料集物件,如果池中沒有空閒的,就新建一個返回。TManagedDataSetType是列舉類,標識只讀資料集和讀寫資料集(只讀資料集可透過CursorType和LockType來加快讀資料速度)。
下面的程式碼是直接從我做的一個專案的源中Copy出來的,有些亂,僅做參考。
unit ManagedDataSet;
interface
uses Ado, CommonDm, SysUtils, DB, dbgrids, ComObj, classes, contnrs;
type
TManagedDataSetType = (ReadOnly, Editable); // 猅羭摸
TXlsExpAdapter = class
private
_sXlsCaption : string;
_sXlileName : string;
_bOverwriteExistFile : Boolean;
_asFieldName : TStringList;
_asXlsTitle : TStringList;
_aDataType : TList;
function GetDataType(const iniIndex : Integer) : TDataType;
function GetFieldName(const iniIndex : Integer) : string;
function GetXlsTitle(const iniIndex : Integer) : string;
public
constructor Create();
destructor Destroy();
property XlsCaption : string read _sXlsCaption Write _sXlsCaption;
property XlsFileName : string read _sXlsFileName Write _sXlsFileName;
property OverWriteExistFile : Boolean read _bOverwriteExistFile Write _bOverwriteExistFile;
procedure AddField(const insFieldName, insCaption : string; const intype : TDataType = ftUnKnown);
procedure GetInfoFromDBGrid(const ingrid : TDBGrid);
property DataType[const iniIndex : Integer] : TDataType read GetDataType;
property FieldName[const iniIndex : Integer] : string read GetFieldName;
property XlsTitle[const iniIndex : Integer] : string read GetXlsTitle;
function Count() : Integer;
end;
TManagedDataSet = class(TAdoDataSet)
private
_source : TDataSource;
_type : TManagedDataSetType;
_bUsed : Boolean;
procedure SetDataSetType(const intype : TManagedDataSetType);
function GetDataSource() : TDataSource;
public
constructor Create(const intype : TManagedDataSetType = Editable);
destructor Destroy(); overr;
procedure Use();
procedure Free(); reintroduce; // 灤護髏?篎ree?ぃ穦睦?龜ㄒ
property DataSetType : TManagedDataSetType read _type Write SetDataSetType;
property IsUsed : Boolean read _bUsed;
property Source : TDataSource read GetDataSource;
function ExportToXls(const inadapter : TXlsExpAdapter) : Boolean;
end;
implementation
function TXlsExpAdapter.Count() : Integer;
begin
Result := _asFieldName.Count;
end;
function TXlsExpAdapter.GetXlsTitle(const iniIndex : Integer) : string;
begin
if (iniIndex >= 0) and (iniIndex <= _aDataType.Count-1) then
begin
Result := _asXlsTitle[iniIndex];
end;
end;
function TXlsExpAdapter.GetFieldName(const iniIndex : Integer) : string;
begin
if (iniIndex >= 0) and (iniIndex <= _aDataType.Count-1) then
begin
Result := _asFieldName[iniIndex];
end;
end;
function TXlsExpAdapter.GetDataType(const iniIndex : Integer) : TDataType;
begin
if (iniIndex >= 0) and (iniIndex <= _aDataType.Count-1) then
begin
Result := TDataType(_aDataType[iniIndex]);
end;
end;
procedure TXlsExpAdapter.GetInfoFromDBGrid(const ingrid : TDBGrid);
var
i, j : Integer;
dt : TDataType;
begin
for i := 0 to ingrid.Columns.Count-1 do
begin
if ingrid.Columns[i].Visible then
begin
dt := ftUnknown;
for j := 0 to ingrid.FieldCount-1 do
begin
if ingrid.Columns[i].FieldName = ingrid.Fields[j].FieldName then
begin
dt := ingrid.Fields[j].DataType;
Break;
end;
end;
Self.AddField(ingrid.Columns[i].FieldName, ingrid.Columns[i].Title.Caption, dt);
end;
end;
end;
procedure TXlsExpAdapter.AddField(const insFieldName, insCaption : string; const intype : TDataType = ftUnKnown);
var
iIndex : Integer;
begin
iIndex := _asFieldName.IndexOf(insFieldName);
if iIndex = -1 then
begin
_asFieldName.Add(insFieldName);
_asXlsTitle.Add(insCaption);
_aDataType.Add(TObject(intype));
end
else begin
_asFieldName[iIndex] := insFieldName;
_asXlsTitle[iIndex] := insCaption;
_aDataType[iIndex] := TObject(intype);
end;
end;
constructor TXlsExpAdapter.Create();
begin
_asFieldName := TStringList.Create();
_asXlsTitle := TStringList.Create();
_aDataType := TObjectList.Create();
end;
destructor TXlsExpAdapter.Destroy();
begin
end;
function TManagedDataSet.ExportToXls(const inadapter : TXlsExpAdapter) : Boolean;
var
obj : OleVariant;
i : Integer;
begin
Result := False;
if not Self.Active then
Exit;
try
excelobj := CreateOleObject('Excel.Application');
excelobj.WorkBooks.Add;
except
Exit;
end;
if FileExists(inadapter.XlsFileName) and inadapter.OverWriteExistFile then
begin
DeleteFile(PChar(inadapter.XlsFileName));
end
else begin
excelobj.Quit;
Exit;
end;
for i := 0 to inadapter.Count-1 do
begin
end;
end;
constructor TManagedDataSet.Create(const intype : TManagedDataSetType = Editable);
begin
inherited Create(nil);
Self.Connection := DmCommon.Cnn;
Self.CursorLocation := clUseClient;
Self.Prepared := True;
Self.CacheSize := 1000;
if intype = ReadOnly then
begin
Self.CursorType := ctOpenForwardOnly;
Self.LockType := ltReadOnly;
end
else if intype = Editable then
begin
Self.CursorType := ctStatic;
Self.LockType := ltOptimistic;
end;
_type := intype;
_bUsed := False;
end;
destructor TManagedDataSet.Destroy();
begin
if Self.Active then
begin
Self.Close;
end;
if Assigned(_source) then
begin
FreeAndNil(_source);
end;
inherited Destroy();
end;
procedure TManagedDataSet.Use();
begin
if _bUsed then
begin
raise Exception.Create('Cannot get a used managed dataset !');
end;
_bUsed := True;
end;
procedure TManagedDataSet.Free();
begin
if Self.Active then
begin
Self.Close;
end;
Self.CommandText := '';
Self.Parameters.Clear; // 睲埃把計
Self.MasterFields := ''; // 睲埃??琿
Self.DataSource := nil;
Self.ExecuteOptions := []; // 睲埃磅︽匡兜
_bUsed := False;
end;
procedure TManagedDataSet.SetDataSetType(const intype : TManagedDataSetType);
begin
if intype = _type then
Exit;
if intype = ReadOnly then
begin
Self.CursorType := ctOpenForwardOnly;
Self.LockType := ltReadOnly;
end
else if intype = Editable then
begin
Self.CursorType := ctStatic;
Self.LockType := ltOptimistic;
end;
end;
function TManagedDataSet.GetDataSource() : TDataSource;
begin
if not Assigned(_source) then
begin
_source := TDataSource.Create(nil);
_source.AutoEdit := False;
_source.DataSet := Self;
end;
Result := _source;
end;
end.
unit DataSetPool; // 癘魁棟????GlobalVarい承????セ摸??Ы龜ㄒ跑秖
interface
uses ManagedDataSet, Contnrs, SysUtils, AdoDb, Db, CommonDm;
type
TDataSetPool = class
private
_ads : TObjectList;
function GetCount() : Integer;
public
constructor Create(const ini : Integer = 10);
destructor Destroy(); override;
property Count : Integer read GetCount;
function GetDataSet(const intype : TManagedDataSetType = Editable) : TManagedDataSet;
function GetAdoCommand() : TAdoCommand; // 度????TAdoCommand?睦?パ秸ノ?璽砫
end;
implementation
constructor TDataSetPool.Create(const ini : Integer = 10);
begin
_ads := TObjectList.Create;
end;
destructor TDataSetPool.Destroy();
begin
FreeAndNil(_ads);
end;
function TDataSetPool.GetCount() : Integer;
begin
Result := _ads.Count;
end;
function TDataSetPool.GetDataSet(const intype : TManagedDataSetType = Editable) : TManagedDataSet;
var
i : Integer;
begin
Result := nil;
for i := 0 to _ads.Count-1 do
begin
if (not TManagedDataSet(_ads[i]).IsUsed) and (TManagedDataSet(_ads[i]).DataSetType = intype) then
begin
Result := TManagedDataSet(_ads[i]);
Result.Use;
break;
end;
end;
if Result = nil then
begin
_ads.Add(TManagedDataSet.Create(intype));
Result := TManagedDataSet(_ads[_ads.Count-1]);
Result.Use;
end;
end;
function TDataSetPool.GetAdoCommand() : TAdoCommand;
begin
Result := TADOCommand.Create(nil);
Result.Connection := DmCommon.Cnn;
end;
end.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-960621/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在CGI中實現session的想法和實現 (轉)Session
- NFT 的建立和轉移功能實現
- 用setjmp和longjmp實現跳轉
- js實現的字串和陣列的相互轉換JS字串陣列
- | / - 的旋轉效果實現(轉)
- js實現的陣列和CSV格式的相互轉換JS陣列
- Spark實現行列轉換pivot和unpivotSpark
- jQuery物件和DOM物件之間的轉換實現jQuery物件
- SOCKET實現廣播(BoardCast)的傳送和接收 (轉)AST
- NIS下solaris和linxu的client實現AutoFS(轉)client
- 使用RxJava實現ImageView的拖動、旋轉和縮放RxJavaView
- jQuery和css3實現的摩天輪旋轉效果jQueryCSSS3
- Java 實現 Map 和 Object 互相轉換的幾種方法JavaObject
- RGB和HSL之間的轉換 C++實現C++
- 滑鼠螢幕取詞技術的原理和實現 (轉)
- C#中使用反射的使用實現和效能分析(轉)C#反射
- python實現中文和unicode轉換PythonUnicode
- camunda如何實現流程跳轉和流程退回
- 實現 Swing 的 JTables 和 Excel 間的複製和貼上功能 (轉)Excel
- asp實現批次錄入資料的實現 (轉)
- 【JavaScript框架封裝】JavaScript中的文字字串的轉義和反轉義的實現JavaScript框架封裝字串
- Unicode編碼和中文互轉(JAVA實現)UnicodeJava
- office轉pdf和圖片實現線上預覽
- canvas實現太陽、地球和月亮旋轉效果Canvas
- JS實現全半形轉換和去空格JS
- Linux : select()詳解 和 實現原理【轉】Linux
- 我的CLog的實現 (轉)
- [顏色進位制轉換]js實現rgb和hex的相互轉換JS
- Activemq和Lingo實現JMS和非同步呼叫(轉)MQGo非同步
- PHP 實現字串翻轉(包含中文漢字)的實現PHP字串
- Js中實現拼音和UrlEncode的功能(利用GB和Unicode對照表) (轉)JSUnicode
- iOS端音訊邊錄邊轉和聲波圖的實現iOS音訊
- Android中實現JSON字串和JSON物件的轉換AndroidJSON字串物件
- 80埠入侵 CGI掃描器的原理和實現過程(轉)
- 用ruby實現簡體中文和繁體中文的相互轉化
- 自動安裝程式的實現演算法和原始碼 (轉)演算法原始碼
- 在C#裡實現DATAGRID的列印預覽和列印 (轉)C#
- Python 實現Excel和TXT文字格式之間的相互轉換PythonExcel