В моем приложении есть время разработки TFDConnection
, которое повторно используется при подключении к другой базе данных (тип).
Я также получаю объединенное соединение из его настроек и регистрирую его с помощью FDManager.AddConnectionDef
для использования при многопоточности (как здесь).
При настройке во второй раз я случайно снова позвонил AddConnectionDef
с тем же ConnectionDefName. В документации говорится:
Имя должно быть уникальным среди других определений подключения в списке ConnectionDefs, в противном случае возникает исключение.
Этого не происходит. Никаких исключений не возникает, я просто получаю два ConnectionDef с одинаковыми именами.
Для любопытных: следующий блок кода демонстрирует такое поведение (RSP-19107 на портале качества). Это не моя непосредственная проблема, потому что я подумал Ну, тогда я использую DeleteConnectionDef
, чтобы сначала удалить старый.
Но оказывается, что это не работает либо. См. второй блок кода.
procedure TFrmFireDACConnectionNames.BtnBug1Click(Sender: TObject);
var
lParams: TStringList;
i,l : integer;
begin
lParams := TStringList.Create;
lParams.Add('User_Name=sysdba');
lParams.Add('Password=masterkey');
lParams.Add('database=D:\Testing\test.gdb');
lParams.Add('Server=localhost');
lParams.Add('Pooled=true');
lParams.Add('DriverID=FB');
FDManager.AddConnectionDef('FBPooled','FB',lParams);
lParams.Values['database'] := 'D:\Testing\test2.gdb';
FDManager.AddConnectionDef('FBPooled','FB',lParams);
// This shows the two identical ConnectionDefs (inspect lParams):
lParams.Clear;
l := FDManager.ConnectionDefs.Count;
for i := 0 to l-1 do
lParams.Add(FDManager.ConnectionDefs[i].Name);
// Contents on my machine:
// Access_Demo
// Access_Demo_Pooled
// DBDEMOS
// EMPOYEE
// MSSQL_Demo
// RBDemos
// SQLite_Demo
// SQLite_Demo_Pooled
// FBPooled <== Duplicates
// FBPooled
// To check that the two added have their respective Params, inspect lParams with breakpoints on the lines below:
lParams.Assign(FDManager.ConnectionDefs[l-1].Params);
// Contents on my machine:
// User_Name=sysdba
// Password=masterkey
// database=D:\Testing\test2.gdb
// Server=localhost
// Pooled=true
// DriverID=FB
// Name=FBPooled
lParams.Assign(FDManager.ConnectionDefs[l-2].Params);
// Contents on my machine:
// User_Name=sysdba
// Password=masterkey
// database=D:\Testing\test.gdb
// Server=localhost
// Pooled=true
// DriverID=FB
// Name=FBPooled
lParams.Free;
end;
Ниже приведен пример кода, демонстрирующий сбой DeleteConnectionDef
. Обратите внимание, что я даже не использую и не открываю файл TFDConnection
.
procedure TFrmFireDACConnectionNames.BtnDeleteTestClick(Sender: TObject);
var
lParams : TStringList;
i,l : integer;
lConnName: String;
begin
lParams := TStringList.Create;
lConnName := 'MyConnPooled';
lParams.Add('DriverID=FB');
lParams.Add('User_Name=sysdba');
lParams.Add('Password=masterkey');
lParams.Add('Database=d:\Testing\Diverse\FireDACConnectionNames\test.gdb');
lParams.Add('Server=localhost');
lParams.Add('Pooled=true');
FDManager.AddConnectionDef(lConnName,'FB',lParams);
lParams.Clear;
lParams.Add('DriverID=MSSQL');
lParams.Add('User_Name=test');
lParams.Add('Password=test');
lParams.Add('Database=test');
lParams.Add('Server=VS20032008');
lParams.Add('Pooled=true');
for l := FDManager.ConnectionDefs.Count-1 downto 0 do
if FDManager.ConnectionDefs[l].Name = lConnName then
begin
FDManager.DeleteConnectionDef(lConnName); // This gets executed
Break;
end;
FDManager.AddConnectionDef(lConnName,'MSSQL',lParams);
// Check ConnectionDefs (inspect lParams):
lParams.Clear;
l := FDManager.ConnectionDefs.Count;
for i := 0 to l-1 do
lParams.Add(FDManager.ConnectionDefs[i].Name);
// Contents on my machine:
// Access_Demo
// Access_Demo_Pooled
// DBDEMOS
// EMPLOYEE
// MSSQL_Demo
// RBDemos
// SQLite_Demo
// SQLite_Demo_Pooled
// MyConnPooled <== Still duplicate
// MyConnPooled
lParams.Free;
end;
Так что же здесь происходит и как это исправить?
Это Delphi Tokyo 10.2.1
Если вы хотите запустить этот код, поместите TFDPhysFBDriverLink
и TFDPhysMSSQLDriverLink
в форму. Я пытался вызвать .Release для них, но это не помогло.
Исправление: размещение компонентов TFDPhysxxxDriverLink не обязательно для запуска кода. Я оставляю это предложение, потому что наличие связанных с ними единиц важно для ошибки AddConnectionDefinition (см. утвержденный ответ).
Устранена проблема: исправления для FireDAC.Stan.Def.pas
и FireDAC.Comp.Client.pas
доступны по ссылке RSP-19107.