使用RAD Studio 11.2构建器创建的DataSnap Delphi 服务器中的同步通信问题

lokaqttq  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(191)

我在使用RAD Studio 11.2默认构建器创建的DataSnap Delphi 服务器时遇到了问题。服务器使用HTTP REST通信并连接到Oracle 11g数据库。我需要多个设备同时与它通信。但是,当同时连接多个设备时,我出现了通信错误。
当我一次只使用一个设备时,没有通信问题。但是,当我尝试使用FireDAC组件同时连接两个设备与数据库通信时,FireDAC与数据库之间的通信出现错误。如果我使用ADODB组件与数据库进行通信,那么在同时使用三个设备时就会出现问题。
我已经检查了驱动程序和数据库,当被其他语言使用时,两者都能正常工作。我还审查了连接关闭功能,并相信它们被正确处理。
DataSnap服务器使用默认配置从RAD Studio 11.2构建器创建。
在这个服务器中我有几个函数,所有这些函数都与数据库通信以插入,更新或选择。函数如下所示:

function TMesaControl.acceptMesa(AJSON: TJSONObject): TJSONValue;
Var
  VMesa: TMesaModel;
  VQry: TADOQuery;
  SQL : string;
begin
  try
    VQry := TSistemaControl.GetInstance().Conexao.CriarQuery();
    VMesa := TJson.JsonToObject<TMesaModel>(AJSON);

    SQL := 'INSERT INTO TAB_MOB_MESA ( ';
    SQL := SQL + 'MOB_SEQUENCIA, ';
    SQL := SQL + 'MOB_MESA, ';
    SQL := SQL + 'MOB_STATUS ';
    SQL := SQL + ') VALUES ( ';
    SQL := SQL + Chr(39) + VMesa.MESA_SEQUENCIA + Chr(39) + ', ';
    SQL := SQL + Chr(39) + VMesa.MESA_NUMERO + Chr(39) + ', ';
    SQL := SQL + Chr(39) + VMesa.MESA_STATUS + Chr(39);
    SQL := SQL + ')';

    VQry.SQL.Text := SQL;
    VQry.ExecSQL;
  finally
    Result := TJson.ObjectToJsonObject(VMesa);
    FreeAndNil(VQry);
    FreeAndNil(VMesa);
  end;
end;

TMesaModel类只是用于接收JSON数据,并且只是我期望接收的数据结构。
TSystemControl类如下所示:

unit uSistemaControl;

interface

uses
  uConexao,
  System.SysUtils;

type
  TSistemaControl = class
  private
    FConexao     : TConexao;
    class var FInstance: TSistemaControl;
  public
    constructor Create();
    destructor Destroy; override;
    class function GetInstance: TSistemaControl;
    property Conexao: TConexao read FConexao write FConexao;
  end;

implementation

{ TSistemaControl }

constructor TSistemaControl.Create();
begin
  FConexao := TConexao.Create;
end;

destructor TSistemaControl.Destroy;
begin
  FConexao.Free;
  inherited;
end;

class function TSistemaControl.GetInstance: TSistemaControl;
begin
  if not Assigned(Self.FInstance) then
  begin
    Self.FInstance := TSistemaControl.Create();
  end;
  Result := Self.FInstance;
end;

end.

最后,这是TConexao类:

unit uConexao;

interface

uses
   ADODB;

type
  TConexao = class
  private
    ADOConnection: TADOConnection;
    procedure ConfigurarConexao;
  public
    constructor Create;
    destructor Destroy; override;
    function GetConn: TADOConnection;
    function CriarQuery: TADOQuery;
    {
    function CriarStoredProc: TFDStoredProc;
    }
  end;

implementation

uses
  uFormPrincipal;

{ TConexao }

procedure TConexao.ConfigurarConexao;
begin
  ADOConnection.ConnectionString := 'Provider=ORAOLEDB.ORACLE;Data Source=' + database_name + ';User ID=' + user_id + ';Password=' + database_pwd;
  ADOConnection.Open;
end;

constructor TConexao.Create;
begin
  ADOConnection := TADOConnection.Create(nil);

  Self.ConfigurarConexao();
end;

function TConexao.CriarQuery: TADOQuery;
var
  VQuery: TADOQuery;
begin
  VQuery := TADOQuery.Create(nil);
  VQuery.Connection := ADOConnection;
  Result := VQuery;
end;

destructor TConexao.Destroy;
begin
  ADOConnection.Free;
  inherited;
end;

function TConexao.GetConn: TADOConnection;
begin
  Result := ADOConnection;
end;

end.

变量database_name、user_id和database_pwd是在创建主窗体时声明的全局变量。
我想知道我能做些什么来解决这个问题。

ukqbszuj

ukqbszuj1#

ADoConnection(就像FireDac连接一样)不能在线程之间共享:
Ok to use TADOConnection in threads
这解释了不能从多个线程使用TADOConnection对象。每个线程都需要创建自己的数据库连接。
FireDac以类似的方式工作:https://docwiki.embarcadero.com/RADStudio/Sydney/en/Multithreading_(FireDAC)
如果满足以下条件,FireDAC是线程安全的:连接对象和与之关联的所有对象(如TFDQuery、TFDTransaction等)在每个时刻都由单个线程使用。
这两种技术都支持连接池,但以优化性能。

相关问题