В FireDac нет простого способа поддерживать резьбовые соединения. По умолчанию соединение FireDac не безопасно. Это означает, что если вы попытаетесь делать вещи в базе данных с несколькими потоками одновременно, используя одно и то же соединение, это может (и обычно) привести к исключениям. Эта библиотека содержит решение для этого через пул соединений, что облегчает это.
Пул соединений предполагает, что вы работаете с определениями соединений. Это легко реализовать, даже динамически, если не используется по умолчанию. Пример можно найти в основной форме приложения. Пул соединений можно использовать для запроса соединения. Пул проверяет, существует ли уже подключение для потока и данного определения соединения. Если так, то соединение возвращается, если нет, оно создается и зарегистрировано. Чтобы сохранить эту администрацию правильным во время выполнения приложения, была добавлена реализация синглтона.
Вы можете зарегистрировать имя для определения подключения по умолчанию в пуле соединений, поэтому вам не нужно указывать его каждый раз. Идентификатор потока, запрашивающего соединение, также может быть автоматически определен пулом.
Существует также базовый класс для потоков, которые хотят использовать пул соединений. Пример с использованием этого базового класса также включен и разработан в основной форме приложения.
Включите ThreadedConnections.Singleton в свой проект или модуль данных. Вызовите метод SetConnectionPoolDefaults для инициализации синглтона для пула соединений. Например:
SetConnectionPoolDefaults('SQLite', 'MainDatabase');
В этом примере 'SQLite' является драйвером и 'MainDatabase' именем вашего определения соединения.
Если определения соединения не используются, вы можете легко создавать их динамически, используя те же параметры, что и ваше соединение. В следующем примере предполагается, что существует соединение, называемое dmDatabase.DbConnection .
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;
При использовании Singleton его экземпляр может быть извлечен с помощью функции GetConnectionPool . Эта функция доступна в блоке ThreadedConnections.Singleton . Пул имеет доступ к ряду функций GetConnection для запроса соединения. Вариант без параметров предполагает, что вы делаете это для определения подключения по умолчанию и для текущего потока. Это также может быть основной поток.
var Pool := GetConnectionPool;
var DefaultConnection := Pool.GetConnection;
var SpecificConnection := Pool.GetConnection('FinancialDatabase', Self.ThreadID);
Вы можете использовать TThreadedConnectionThread в качестве суперкласса для ваших потоков. Этот класс ожидает экземпляра пула соединений при создании. Он обеспечивает стандартные функции, чтобы легко получить соединение в подклассах. Пример этого можно найти в ThreadedConnections.Example.Threads . Конечно, также возможно использовать SuperClass в качестве примера для реализации в вашем собственном Superclass для потоков.
Вот пример, как использовать его при использовании TThreadedConnectionThread в качестве SuperClass:
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;