清幽傲竹实现kbmMWServer的方法(转)

感谢竹子!

整体思路,是不用kbmMWUNIDACQuery,而是直接用uniQuery做数据查询,利用kbmMWUNIDACConnectioPool取得数据库联接,自己再建一个uniQuery对象池,从中取uniQuery.
下面是一个具体查询数据库的方法:
function TSchoolSrv.PerformGetStuAttendanceState(
  ClientIdent: TkbmMWClientIdentity;
  const Args: array of Variant): Variant;
var
  aUniQuery: TUniQuery;
  aconn: TkbmMWUNIDACConnection;
  json: string;
  code: Integer;
  msg: string;
  student_name,class_name: string;
  memTable: TkbmMemTable;
  aStreamFormat: TkbmMWBinaryStreamFormat;
begin
  code := -1;
  memTable := nil;
  aUniQuery := nil;
  aStreamFormat := nil;  
  aconn := FDM.getkbmMWUNIDACConnection;
  if aconn = nil then  kbmMWRaiseException(101,‘无可用的数据库连接.‘);

try
      aUniQuery := UniQueryPool.Lock;
      if aUniQuery = nil then kbmMWRaiseServerException(‘无可用的数据集对象.‘);

aUniQuery.Connection := aconn.Database;
      aUniQuery.SQL.Text := ‘select attendance_state_code,attendance_state from attendance.stu_attendance_state‘;
      aUniQuery.sql.Text := fdm.getFinalSql(aUniQuery.sql.Text);//多库合一库时重组SQL语句
      aUniQuery.Open;
      memTable := kbmMemTablePool.Lock;
      if memTable = nil then kbmMWRaiseServerException(‘无可用的内存表对象.‘);
      memTable.LoadFromDataSet(aUniQuery,[mtcpoStructure,mtcpoProperties]);
      aStreamFormat := kbmMWBinaryStreamFormatPool.Lock;
      if aStreamFormat = nil then  kbmMWRaiseServerException(‘无可用的StreamFormat对象.‘);
      memTable.SaveToStreamViaFormat(ResultStream,aStreamFormat);
    except
      on e: Exception do
      begin
         kbmMWRaiseException(999,e.Message);
      end;  
    end;

finally
    if aUniQuery <> nil then UniQueryPool.UnLock(aUniQuery);
    if memTable <> nil then kbmMemTablePool.UnLock(memTable);
    if aStreamFormat <> nil then kbmMWBinaryStreamFormatPool.UnLock(aStreamFormat);
    aconn.UnlockConnection;
  end;
end;

下面这个方法,从kbmMWUNIDACConnectionPool取得一个可用的数据库联接.function TFDM.getkbmMWUNIDACConnection: TkbmMWUNIDACConnection;

begin
  Result := TkbmMWUNIDACConnection(kbmMWUNIDACConnectionPool1.GetBestConnection(True,0,nil,3000));
end;

最后,再看看uniQuery池管理对象的实现,整个单元,不多解释.

unit UUniQueryPool;

interface

uses
  Classes, Windows, SysUtils, Uni, forms;

type
  TUniQueryPool = class(TObject)
  private
    FObjList:TThreadList;
    FTimeout: Integer; //单位:毫秒
    FMaxCount: Integer;
    FSemaphore: Cardinal;
    function CreateNewInstance(List:TList): TUniQuery;
    function GetLock(List:TList;Index: Integer): Boolean;
    function getUsedCount: Integer;
  public
    property Timeout:Integer read FTimeout write FTimeout;
    property MaxCount:Integer read FMaxCount;
    property usedCount: integer read getUsedCount;

constructor Create(ACapicity:Integer);overload;
    destructor Destroy;override;
    function Lock: TUniQuery;
    procedure UnLock(var Value: TUniQuery);
  end;

var
  UniQueryPool: TUniQueryPool;

implementation

constructor TUniQueryPool.Create(ACapicity:Integer);
begin
  FObjList:=TThreadList.Create;
  FTimeout := 3000;
  FMaxCount := ACapicity;
  FSemaphore := CreateSemaphore(nil, FMaxCount, FMaxCount, nil);   
end;

function TUniQueryPool.CreateNewInstance(List:TList): TUniQuery;
var
  p: TUniQuery;
begin
  try
    p := TUniQuery.Create(nil);
    p.Tag := 1;
    List.Add(p);
    Result := p;
  except
    Result := nil;
    Exit;
  end;
end;

destructor TUniQueryPool.Destroy;
var
  i: Integer;
  List:TList;
begin
  List:=FObjList.LockList;
  try
    for i := List.Count - 1 downto 0 do
    begin
      TUniQuery(List[i]).Free;
    end;
  finally
    FObjList.UnlockList;
  end;
  FObjList.Free;
  FObjList := nil;
  CloseHandle(FSemaphore);
  inherited Destroy;
end;

function TUniQueryPool.GetLock(List:TList;Index: Integer): Boolean;
begin
  try
    Result := TUniQuery(List[Index]).Tag = 0;
    if Result then
      TUniQuery(List[Index]).Tag := 1;
  except
    Result :=False;
    Exit;
  end;
end;

function TUniQueryPool.getUsedCount: Integer;
var
  i: Integer;
  List:TList;
begin
  try
    Result := 0;
    list := FObjList.LockList;
    Result := list.Count;
  finally
    FObjList.UnlockList;
  end;  
end;

function TUniQueryPool.Lock: TUniQuery;
var
  i: Integer;
  List:TList;
begin
  try
    Result := nil;
    if WaitForSingleObject(FSemaphore, Timeout) = WAIT_FAILED then Exit;
    List:=FObjList.LockList;
    try
      for i := 0 to List.Count - 1 do
      begin
        if GetLock(List,i) then
        begin
          Result := TUniQuery(List[i]);
          //PostMessage(Application.MainForm.Handle, 8888,23,0);
          Exit;
        end;
      end;
      if List.Count < MaxCount then
      begin
        Result := CreateNewInstance(List);
        //PostMessage(Application.MainForm.Handle, 8888,21,0);
      end;
    finally
      FObjList.UnlockList;
    end;
  except
    Result :=nil;
    Exit;
  end;
end;

procedure TUniQueryPool.Unlock(var Value: TUniQuery);
var
  List:TList;
begin
  try
    List:=FObjList.LockList;
    try
      TUniQuery(List[List.IndexOf(Value)]).Tag :=0;
      ReleaseSemaphore(FSemaphore, 1, nil);
    finally
      FObjList.UnlockList;
    end;
    //PostMessage(Application.MainForm.Handle, 8888, 22, 0);
  except
    Exit;
  end;
end;

initialization
  UniQueryPool := TUniQueryPool.Create(100);
finalization
  FreeAndNil(UniQueryPool);

end.

时间: 2024-10-12 13:18:10

清幽傲竹实现kbmMWServer的方法(转)的相关文章

清幽傲竹实现的kbmMWServer数据库联接失败重联(转载红鱼儿)

1.修改kbmMWUnidac单元的TkbmMWUNIDACConnection.InternalOpenConnection方法,加上: //支持unidac重联           FDatabase.Options.LocalFailover:=Options.LocalFailover;           FDatabase.OnConnectionLost:=OnConnectionLost;           FDatabase.AfterConnect:=AfterConnec

xalion三层与Web开发帖子一览表 good

使用http.sys,让delphi 的多层服务飞起来(Delphi借用http.sys充当http服务器,也就可以发送返回JSON等信息,当然浏览器也可以使用)http://www.cnblogs.com/xalion/p/6219515.html使用delphi 10.2 开发linux 上的webservice(客户端调用服务端的函数)http://www.cnblogs.com/xalion/p/6683165.htmlUbuntu 中用 delphi 开发 apache(输出HTML文

初始kbmmw 中的ORM

在kbmmw 5.02.1 中,加入了ORM 的功能(这里可能和其他语言的定义不完全一样),我们就简单的认为 它就是一个类与数据库的转换吧.今天就先介绍一下如何通过kbmmw 的ORM 功能,实现类与数据库的相互 转换和操作. 前提条件:delphi 10.2.1 kbmmw 5.02.1 unidac 7.0.2 haosql for sql server 2008  非常不错的一个sql 管理器 启动haosql  for sqlserver2008 管理器,启动数据库. 打开delphi

Unity 崩溃问题解决方法——之一

友情提示:工作随记,不喜勿喷 注意:文艺青年可以略过,暴力青年欢迎采纳 Library文件夹 Unity每次编译都会生成这个东西,不用担心丢失的问题.所以,干掉他! 选中 + Delete   或者  选中 + Shift  + Delete 网上看了很多方法,就觉得这个简单,粗暴,是我喜欢的类型. 优点:上面说了 缺点:如果工程过大,重新编译时间会比较长.(但是对于查Log日志来说,相对快点)

Java TM 已被阻止,因为它已过时需要更新的解决方法

公司的堡垒机需要通过浏览器登陆,且该堡垒机的网站需要Java的支持,最近通过浏览器登陆之后总是提示"java TM 已被阻止,因为它已过时需要更新的解决方法"导致登陆之后不能操作, 但是操作系统中确实已经安装了比较新的JDK,安装的JDK版本是jdk-7u67-windows-i586,因为太烦人,所以决定搞清楚报错的原因,一劳永逸,彻底解决这个问题 准备工作:安装JDK,安装版本jdk-7u67-windows-i586.exe,因为机器的Eclipse还依赖64位的JDK,所以另安

win7 64位系统 PB连接oracle数据库出现“oracle library oci.dll could not be loaded”问题的解决方法

今天与大家分享一个自己的学习笔记,希望能给遇到同样问题的人带来帮助. 不知道大家在win7 64位系统下用 PB连接oracle数据库时,是否遇到过“oracle library oci.dll could not be loaded”问题. 今天,在win7 64位系统下用 PB连接oracle数据库时,一直出现上述错误,在百度上找了很久,都没有找到一个完整的解决方案,咨询了很多人,(他们都说是我的PB和oracle没装好,但我装的时候没出现任何问题,一切都很顺利,而且PB和oracle都能正

C#与数据库访问技术总结(八)之ExecuteNonQuery方法

ExecuteNonQuery方法 ExecuteNonQuery方法主要用来更新数据. 通常使用它来执行Update.Insert和Delete语句. 该方法返回值意义如下: 对于Update.Insert和Delete语句,返回值为该命令所影响的行数. 对于所有其他类型的语句,返回值为-1. Command对象通过ExecuteNonQuery方法更新数据库的过程非常简单,需要进行的步骤如下: (1)创建数据库连接. (2)创建Command对象,并指定一个SQL Insert.Update

android开发之onCreate( )方法详解

onCreate( )方法是android应用程序中最常见的方法之一,那么,我们在使用onCreate()方法的时候应该注意哪些问题呢? 先看看Google Android Developers官网上的解释: onCreate(Bundle) is where you initialize your activity. Most importantly, here you will usually call setContentView(int) with a layout resource d

MAC平台下Xcode配置使用OpenCV的具体方法 (2016最新)

1.序言: 1.1 背景 本人小白一枚,不过因为最近在从事机器视觉方面的工作,所以接触到OpenCV. 因为工作需求,本人要在MAC端使用OpenCV实现一些视觉功能,配置环境成了最大的阻碍,网上查了很多相关资料和博客,都因为版本环境问题屡试屡败,不过经历重重尝试,笔者最终还是配置成功并运行了自己的源码.当然成功的关键还是因为笔者站在了巨人的肩膀上,借鉴了很多网上的教程,为了不误导大家配置的过程,参考文章的地址统一放在文章里,望各位大大看见之后能够理解,废话不说进入正题. 1.2 环境说明 如果