我在使用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是在创建主窗体时声明的全局变量。
我想知道我能做些什么来解决这个问题。
1条答案
按热度按时间ukqbszuj1#
ADoConnection(就像FireDac连接一样)不能在线程之间共享:
Ok to use TADOConnection in threads
这解释了不能从多个线程使用TADOConnection对象。每个线程都需要创建自己的数据库连接。
FireDac以类似的方式工作:https://docwiki.embarcadero.com/RADStudio/Sydney/en/Multithreading_(FireDAC)
如果满足以下条件,FireDAC是线程安全的:连接对象和与之关联的所有对象(如TFDQuery、TFDTransaction等)在每个时刻都由单个线程使用。
这两种技术都支持连接池,但以优化性能。