TManagedDataSet和DataSetPool的實現 (轉)

gugu99發表於2007-08-16
TManagedDataSet和DataSetPool的實現 (轉)[@more@]

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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章