首页 > 学院 > 开发设计 > 正文

TManagedDataSet和DataSetPool的实现

2019-11-18 18:34:00
字体:
来源:转载
供稿:网友
TManagedDataSet和DataSetPool的实现
 
         天天用Delphi,自己有了很多想法。写代码之余,有空闲时间就把一些东西整理成文档。
         Delphi中使用最多的大概是AdoExPRess组件,这是Borland封装了Microsoft的Ado的东东,使用频率最多的TAdoDataSet对应了Ado原生的RecordSet,在功能上做了一些增强,但用法基本一致,用多了就感觉TAdoDataSet还有扩充和改造的地方。
         由于代码中使用了很多的TAdoDataSet控件,创建和释放对象非常频繁,而且每次创建后都要设置很多基本相同的属性,颇为麻烦。于是想到可以实现一个记录集池,每次当需要一个记录集时,从这个池中得到一个空闲且符合要求的(只读或可读写),用完了就被池回收,如果池中记录集不够,就自动生成新的记录集对象。
         首先要做的是改造TAdoDataSet,我写了一个TManagedDataSet,继承自TAdoDataSet,可以自己知道自己是被人使用还是空闲(通过IsUsed()),重写了Free(),把本来释放的动作改为仅是把自己设置为空闲,并清除状态(session)信息,并可以通过Source()返回一个指向自己的TDataSource对象。
         有了这些基础后,就可以很快的构建TDataSetPool类了,这个类仅是保存可用的TManagedDataSet对象,通过GetDataSet(WantType : TManagedDataSetType)返回一个空闲的数据集对象,如果池中没有空闲的,就新建一个返回。TManagedDataSetType是枚举类,标识只读数据集和读写数据集(只读数据集可通过优化CursorType和LockType来加快读数据速度)。
         下面的代码是直接从我做的一个项目的源文件中Copy出来的,有些乱,仅做参考。
 
 
 
unit ManagedDataSet;
 
interface
 
uses AdoDb, CommonDm, SysUtils, DB, dbgrids, ComObj, classes, contnrs;
 
type
         TManagedDataSetType = (ReadOnly, Editable); // 猅羭摸
    TXlsExpAdapter = class
        private
           _sXlsCaption : string;
            _sXlsFileName : string;
            _bOverwriteExistFile : Boolean;
                            _asFieldName : TStringList;
            _asXlsTitle : TStringList;
            _aDataType : TObjectList;
            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(); override;
                            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
         Excelobj : 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.

上一篇:三层结构的设计模式

下一篇:设置全局快捷键

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
学习交流
热门图片

新闻热点

疑难解答

图片精选

网友关注