Nach dem End geht dann DataSnap daher und läuft über das DataSet, daher ist alles darin, eventuell dennoch nicht threadsicher.
siehe z.B. Optionen ala
TFDAutoFetchAll, wo nach dem Open der
DB-Zugrif noch nicht beendet sein kann.
Erstmal das Prinzip, ohne irgendeine Synchronisation (Synchronize oder CriticalSection), was man für threadsichere Dinge ala TFileStream benutzen kann.
Delphi-Quellcode:
function TdmServerMethodsZMI.ZMI_GetBauDataSetThreadSave(BauNr: Integer): TDataSet;
begin
Result := TFDQuery.Create(nil);
try
Result.Connection := dmZIMPool.conZMI;
Result.SQL.Add('SELECT *');
Result.SQL.Add('FROM BAU');
Result.SQL.Add('WHERE BAUNR = :BAUNR');
Result.Params[0].AsInteger := BauNr;
Result.Open;
except
FreeAndNil(Result);
raise;
end;
end;
Innerhalb mußt du selber die Sicherheit für deine Ressourcen sorgen
und nach dem End übernimmt das DataSnap (wenn es der Owner ist/wird)
Wenn man alles gekapselt hat, dann ginge es auch direkt, da Constructoren sich intern selber absicher. (wenn es knallt, wird automatisch
Free Destroy aufgerufen)
Delphi-Quellcode:
function TdmServerMethodsZMI.ZMI_GetBauDataSetThreadSave(BauNr: Integer): TDataSet;
begin
Result := TMyQuery.Create(nil, dmZIMPool.conZMI, 'SELECT * FROM BAU WHERE BAUNR = :BAUNR', [BauNr]);
end;
Mit einem Synchronize kann man sich überlegen wie man das absicher. (ersteres, wenn man blind davon ausgeht, daß der Rückweg vom Synchronize immer funktioniert)
Delphi-Quellcode:
function TdmServerMethodsZMI.ZMI_GetBauDataSetThreadSave(BauNr: Integer): TDataSet;
var
LDataSet: TDataSet;
begin
TThread.Synchronize(nil, procedure
begin
LDataSet := TFDQuery.Create(nil);
try
LDataSet.Connection := dmZIMPool.conZMI;
LDataSet.SQL.Add('SELECT *');
LDataSet.SQL.Add('FROM BAU');
LDataSet.SQL.Add('WHERE BAUNR = :BAUNR');
LDataSet.Params[0].AsInteger := BauNr;
LDataSet.Open;
except
LDataSet.Free;
raise;
end;
end);
Result := LDataSet;
end;
Delphi-Quellcode:
function TdmServerMethodsZMI.ZMI_GetBauDataSetThreadSave(BauNr: Integer): TDataSet;
var
LDataSet: TDataSet;
begin
LDataSet := nil;
try
TThread.Synchronize(nil, procedure
begin
LDataSet := TFDQuery.Create(nil);
LDataSet.Connection := dmZIMPool.conZMI;
LDataSet.SQL.Add('SELECT *');
LDataSet.SQL.Add('FROM BAU');
LDataSet.SQL.Add('WHERE BAUNR = :BAUNR');
LDataSet.Params[0].AsInteger := BauNr;
LDataSet.Open;
end);
except
LDataSet.Free;
raise;
end;
Result := LDataSet;
end;
PS: Create gehört natürlich grundsätzlich
immer vor das Try, denn wenn es im Create knallt, dann ist im Finally/Except die Variable nicht initialisiert,
was einem der Compiler aber auch sagt, wenn man mal liest was der zu sagen kannt.