Es gibt keinen einfachen Weg in Firedac, um Fadenverbindungen zu unterstützen. Standardmäßig ist die Firedac-Verbindung nicht mit Thread-Safe. Dies bedeutet, dass, wenn Sie versuchen, Dinge in der Datenbank mit mehreren Threads gleichzeitig mit derselben Verbindung zu tun, dies zu Ausnahmen führen (und wird). Diese Bibliothek enthält eine Lösung dazu über einen Verbindungspool, der dies erleichtert.
Der Verbindungspool geht davon aus, dass Sie mit Verbindungsdefinitionen arbeiten. Dies ist einfach zu implementieren, selbst wenn sie standardmäßig nicht verwendet werden. Ein Beispiel finden Sie in der Hauptform der Anwendung. Der Verbindungspool kann verwendet werden, um eine Verbindung anzufordern. Der Pool prüft, ob bereits eine Verbindung für den Thread und die angegebene Verbindungsdefinition vorhanden ist. In diesem Fall wird die Verbindung zurückgegeben, wenn nicht, sie wird erstellt und registriert. Um diese Verwaltung während der Anwendungsausführung korrekt zu halten, wurde eine Implementierung eines Singleton hinzugefügt.
Sie können einen Namen für die Standardverbindungsdefinition im Verbindungspool registrieren, sodass Sie ihn nicht jedes Mal angeben müssen. Die ID des Threads, die eine Verbindung beantragt, kann auch automatisch vom Pool ermittelt werden.
Es gibt auch eine Basisklasse für Threads, die den Verbindungspool verwenden möchten. Ein Beispiel, das diese Basisklasse verwendet, ist ebenfalls enthalten und in der Hauptform der Anwendung ausgearbeitet.
Fügen Sie ThreadedConnections.Singleton in Ihr Projekt- oder Datenmodul ein. Rufen Sie die Methode SetConnectionPoolDefaults auf, um den Singleton für den Verbindungspool zu initialisieren. Zum Beispiel:
SetConnectionPoolDefaults('SQLite', 'MainDatabase');
In diesem Beispiel ist 'SQLite' der Treiber und 'MainDatabase' der Name Ihrer Verbindungsdefinition.
Wenn keine Verbindungsdefinitionen verwendet werden, können Sie sie problemlos mit denselben Parametern wie Ihrer Verbindung dynamisch erstellen. Das folgende Beispiel wird davon ausgegangen, dass eine Verbindung namens dmDatabase.DbConnection besteht.
const DefinitionName = 'MainDatabase';
var Definition := FDManager.ConnectionDefs.FindConnectionDef(DefinitionName);
if not Assigned(Definition) then
begin
var Connection := dmDatabase.DbConnection;
FDManager.AddConnectionDef(DefinitionName, Connection.ActualDriverID, Connection.Params);
end;
Bei der Verwendung des Singleton kann seine Instanz mit der GetConnectionPool -Funktion abgerufen werden. Diese Funktion ist in der ThreadedConnections.Singleton -Einheit verfügbar. Der Pool hat Zugriff auf eine Reihe von GetConnection -Funktionen, um eine Verbindung anzufordern. Die NO -Parametervariante geht davon aus, dass Sie dies für die Standardverbindungsdefinition und für den aktuellen Thread tun. Dies kann auch der Hauptfaden sein.
var Pool := GetConnectionPool;
var DefaultConnection := Pool.GetConnection;
var SpecificConnection := Pool.GetConnection('FinancialDatabase', Self.ThreadID);
Sie können TThreadedConnectionThread als Superklasse für Ihre Threads verwenden. Diese Klasse erwartet eine Instanz des Verbindungspools bei der Erstellung. Es bietet Standardfunktionen, um einfach eine Verbindung in den Unterklassen zu erhalten. Ein Beispiel hierfür finden Sie in ThreadedConnections.Example.Threads . Natürlich ist es auch möglich, die Superklasse als Beispiel für die Implementierung in Ihrer eigenen Superklasse für Threads zu verwenden.
Hier ist ein Beispiel, wie Sie es verwenden, wenn Sie das TThreadedConnectionThread als Superklasse verwenden:
TMyDatabaseThread = class(TThreadedConnectionThread)
protected
procedure Execute; override;
end;
TMyDatabaseThread.Execute;
begin
var Query := TFDQuery.Create;
try
Query.Connection := GetConnection;
...
finally
Query.Free;
end;
end;
var Thread := TMyDatabaseThread.Create(True, GetConnectionPool);
Thread.Start;