Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#13

AW: DataSnap mit mehreren Datenbanken

  Alt 27. Mär 2015, 18:50
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 Delphi-Referenz durchsuchenTFDAutoFetchAll, 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.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (27. Mär 2015 um 22:10 Uhr)
  Mit Zitat antworten Zitat