DLL-Entwicklung (FireDAC)
Nach oben zu Arbeiten mit Verbindungen (FireDAC)
In diesem Thema wird beschrieben, wie FireDAC in den dynamischen Linkbibliotheken verwendet wird.
Inhaltsverzeichnis
Allgemeine Informationen
FireDAC kann in einer DLL wie in einer normalen Anwendung verwendet werden. Entwickler müssen aber zwei spezielle DLL-Entwicklungstechniken berücksichtigen.
Gemeinsame Nutzung von Verbindungen in einer Anwendung und einer DLL
Wenn eine Verbindung von einer Anwendung zu der DLL übertragen werden muss, sollte die Anwendung nicht das TFDCustomConnection-Objekt übertragen, weil dies zu Zugriffsverletzungs- und anderen Fehlern führen kann. Dabei handelt es sich nicht um ein FireDAC-Problem. Das Problem besteht aufgrund der Delphi-RTL/RTTI-Einschränkungen. Eine Verbindung kann nicht mit anderen Prozessen gemeinsam genutzt werden, weil die gemeinsame Nutzung nur innerhalb desselben Adressraums funktioniert.
Um eine Verbindung zwischen einer Anwendung und einer DLL zu übertragen, muss die Anwendung den Wert der Eigenschaft TFDCustomConnection.CliHandle an die DLL übertragen. Hier muss das Handle der Eigenschaft TFDCustomConnection.SharedCliHandle zugewiesen werden.
Nach der Zuweisung an SharedCliHandle kann die DLL-Verbindung durch Setzen von Connected auf True aktiviert werden. Hierzu muss keine Verbindungsdefinition, einschließlich der DriverID, konfiguriert werden. Die Verbindung kann dann als eine normale Datenbankverbindung verwendet werden. Die Verbindung kann schließlich durch Setzen von Connected auf False geschlossen werden. Die physische Verbindung wird dabei nicht geschlossen, deshalb bleibt die Anwendungsverbindung aktiv.
Die Anwendungsverbindung protokolliert keine Statusänderungen, die durch die DLL durchgeführt werden. Daher muss die DLL den Transaktionsstatus beibehalten, der vor dem Aufruf der DLL vorhanden war. In einer DLL sollten keine Transaktionen behandelt sowie keine Transaktions-Isolationsstufen und andere Einstellungen geändert werden.
Darüber hinaus werden durch Setzen von SharedCliHandle keine Optionswerte von dem Anwendungs- zu einem DLL-Verbindungsobjekt übertragen. Die DLL-Verbindungsoptionen können genauso wie die Anwendungsverbindungsoptionen festgelegt werden.
Zum Beispiel: Der DLL-Code:
procedure SomeTask(ACliHandle: Pointer); stdcall;
var
oConn: TFDConnection;
oQuery: TFDQuery;
begin
oConn := TFDConnection.Create(nil);
oQuery := TFDQuery.Create(nil);
try
oConn.SharedCliHandle := ACliHandle;
oConn.Connected := True;
oQuery.Connection := oConn;
oQuery.ExecSQL('delete from aaa');
finally
oQuery.Free;
oConn.Free;
end;
end;
exports
SomeTask;
Und der Anwendungscode:
procedure TForm1.Button1Click(Sender: TObject);
type
TSomeTaskProc = procedure (ACliHandle: Pointer); stdcall;
var
hDll: THandle;
pSomeTask: TSomeTaskProc;
begin
hDll := LoadLibrary(PChar('Project2.dll'));
try
@pSomeTask := GetProcAddress(hDll, PChar('SomeTask'));
FDConnection1.StartTransaction;
try
pSomeTask(FDConnection1.CliHandle);
FDConnection1.Commit;
except
FDConnection1.Rollback;
raise;
end;
finally
FreeLibrary(hDll);
end;
end;
Hinweis: Der Code führt Folgendes nicht aus:
- Behandeln von DLL-Ladefehlern.
- Treffen von Vorkehrungen zum Entladen der FireDAC-DLL – siehe nächstes Kapitel.
- Längeres Beibehalten der geladenen DLL und längeres Beibehalten von DLL-Objekten.
Entladen einer FireDAC-DLL
Eine Anwendung kann beim Entladen einer DLL, die FireDAC enthält, hängen bleiben. Das Standardsymptom dafür ist, dass die Anwendung beim FreeLibrary-Aufruf hängen bleibt. Dies ist eine Einschränkung von FireDAC, für die es zwei Workarounds gibt:
- Aktivieren Sie den FireDAC-Hintergrundmodus ("silent mode") in der DLL, sodass keine Wartecursor, Dialogfelder usw. von FireDAC angezeigt werden. Fügen Sie dazu den folgenden Code in Ihre DLL-DPR-Datei ein:
uses
FireDAC.UI.Intf;
begin
FFDGUIxSilentMode := True;
end.
- Beenden Sie den FireDAC-Manager vor dem Entladen einer DLL. Dafür muss die DLL eine Prozedur exportieren, die die Prozedur ADTerminate aufruft. Fügen Sie dazu den folgenden Code in Ihre DLL-DPR-Datei ein:
uses
FireDAC.Stan.Factory;
procedure Shutdown;
begin
FDTerminate;
end;
exports
Shutdown;
Importieren Sie dann die Prozedur Shutdown aus der Anwendung, und rufen Sie sie vor dem Aufruf von FreeLibrary auf:
var
Shutdown: procedure;
....
Shutdown := GetProcAddress(hLib, 'Shutdown');
if Assigned(Shutdown) then
Shutdown();
FreeLibrary(hLib);
Hinweis: Die obige Vorgehensweise muss für die ActiveX-Server mit integriertem FireDAC verwendet werden.
Siehe auch
Beispiele
- FireDAC DLL Sharing (Beispiel)