2014年5月20日星期二

datasnap里面用连接池

目前FireDac支持连接池,用来给Datasnap做池子,写代码测试了一下。
先写池子的函数
const
  COraclePooledName = 'Ora_Pooled';

function TdmConn.AcquireConnection: TFDConnection;
begin
  log.TrackMethod('TdmConn.AcquireConnection');
  Result := TFDConnection.Create(nil);
  Result.ConnectionDefName := COraclePooledName;
  try
    Result.Connected := True;
  except
    on E: Exception do
    begin
      FreeAndNil(Result);
      log.LogException(E);
      raise E;
    end;
  end;
end;

function TdmConn.ReleaseConnection(var Conn: TFDConnection): Boolean;
begin
  log.TrackMethod('TdmConn.ReleaseConnection');
  Result := True;
  Conn.Close;
  FreeAndNil(Conn);
end;

procedure TdmConn.DataModuleCreate(Sender: TObject);
const
  Section = 'Oracle';
var
  Params: TStringList;
begin
  Params := TStringList.Create;
  with TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')) do
  begin
    FDManager.Close;

    Params.Add(Format('Database=%s', [ReadString(Section, 'ConnStr', '')]));
    Params.Add('Pooled=True');
    Params.Add('DriverID=Ora');
    Params.Add('User_Name=xxx');
    Params.Add('Password=xxx');
    Params.Add('OSAuthent=No');
    Params.Add(Format('POOL_MaximumItems=%d', [ReadInteger(Section, 'PoolMaximumItems', 30)]));
    Params.Add(Format('POOL_CleanupTimeout=%d', [ReadInteger(Section, 'PoolCleanupTimeOut', 30000)]));
    Params.Add(Format('POOL_ExpireTimeout=%d', [ReadInteger(Section, 'PoolExpireTimeout', 90000)]));

    FDManager.AddConnectionDef(COraclePooledName, 'Ora', Params);

    Free;
  end;
  FreeAndNil(Params);
end;

procedure TdmConn.DataModuleDestroy(Sender: TObject);
begin
  FDManager.CloseConnectionDef(COraclePooledName); //close all pooled conn
  FDManager.Close;
end;
然后再使用池子
unit sSample;

interface

uses
  Data.DB, Datasnap.DBClient, Datasnap.Provider,
  FireDAC.Comp.Client, System.SysUtils,
  Data.DBXJSONReflect, System.JSON,
  uServerMethod;

type
  TSmSample = class(TServerMethod)
  public
    function ServerTime: TDateTime;
    function GetTblImage: TDataSet;
  end;

implementation

{ TSmSample }

uses
  dConn, uLog, System.StrUtils;

procedure CopyQueryToClientDataSet(SrcQuery: TDataSet; var DstQuery: TDataSet);
var
  DataSetProvider: TDataSetProvider;
begin
  try
    if DstQuery = nil then
      DstQuery := TClientDataSet.Create(nil); //will be freed by TDSServerConnectionHandler.DbxCommandClose or TDSMethodValues.AssignParameterValues 's ClearReferenceParameters
    DataSetProvider := TDataSetProvider.Create(nil);
    DataSetProvider.DataSet := SrcQuery;
    TClientDataSet(DstQuery).Data := DataSetProvider.Data;
  finally
    FreeAndNil(DataSetProvider);
  end;
end;

function TSmSample.GetTblImage: TDataSet;
var
  Conn: TFDConnection;
  Query: TFDQuery;
begin
  Conn := dmConn.AcquireConnection;
  Query := TFDQuery.Create(nil);

  try
    Query.Connection := Conn;
    Query.SQL.Text := 'SELECT * FROM tbl_image';
    Query.Active := True;
    CopyQueryToClientDataSet(Query, Result);
  finally
    if Assigned(Query) then
      FreeAndNil(Query);
    dmConn.ReleaseConnection(Conn);
  end;
end;

function TSmSample.ServerTime: TDateTime;
var
  Conn: TFDConnection;
  Query: TFDQuery;
begin
  //raise Exception.Create('hahaha');
  Conn := dmConn.AcquireConnection;
  Query := TFDQuery.Create(nil);
  try
    Query.Connection := Conn;
    Query.SQL.Text := 'SELECT sysdate FROM dual';
    Query.Active := True;
    Result := Query.FieldByName('sysdate').AsDateTime;
  finally
    FreeAndNil(Query);
    dmConn.ReleaseConnection(Conn);
  end;
end;

initialization
  RegisterServerMethodClass(TSmSample);

finalization

end.
是不是觉得挺爽,这里需要留意的是由于Conn要在服务方法内一定还给连接池,所以做的TFDQuery需要Copy给TClientDataSet这样的内存DataSet才走的通。

1 条评论:

  1. 您好,刚开始学习DATASNAP,好不容易在网上找到您的文章.能不能发个dConn, uLog,这两个文件学习一下呀.谢谢.

    回复删除