代码之家  ›  专栏  ›  技术社区  ›  Jan Doggen

FDManager。DeleteConnectionDef不删除连接定义

  •  1
  • Jan Doggen  · 技术社区  · 7 年前

    我的应用程序有一个设计时间 TFDConnection 当它连接到另一个数据库(类型)时会被重用。
    我还从其设置中导出池连接,并将其注册到 FDManager.AddConnectionDef 多线程时使用( like here

    第二次设置时,我无意中打电话给 AddConnectionDef 再次使用相同的ConnectionDefName。这个 documentation 说:

    . 没有任何例外,我只是得到了两个同名的connectiondf。
    对于那些好奇的人:下一个代码块演示了这种行为( RSP-19107 on Quality Portal ). 这不是我马上要讨论的问题,因为我认为 那么我用 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;
    

    下面是示例代码,演示了 删除连接EF 弱点注意,我甚至没有使用或打开 TFD连接 .

    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 在你的表格上。我试着打电话。释放这些,但这没有帮助。


    在场 对于AddConnectionDefinition错误来说,它们的相关单元是必不可少的(请参阅批准的答案)。


    问题已解决:的修补程序 FireDAC.Stan.Def.pas FireDAC.Comp.Client.pas 在那里可以买到 RSP-19107 链接

    1 回复  |  直到 7 年前
        1
  •  4
  •   Victoria zac    7 年前

    如何删除连接定义?

    顺便说一句,这种循环没有什么意义,因为删除方法需要的是名称,而不是索引,因此直接调用它基本上具有相同的效果:

    FDManager.DeleteConnectionDef(lConnName);
    

    这样做可以避免上述引用计数增加。但是继续阅读。

    如何防止连接定义名称重复?

    但要从根本上解决你的问题。连接定义名称必须真正唯一,这是管理器应该注意的。不幸的是,由于您发现的错误,没有。在修复之前,您只需在添加之前询问是否存在此类名称的连接定义:

    if not FDManager.IsConnectionDef('FBPooled') then
      FDManager.AddConnectionDef('FBPooled', 'FB', Params)
    else
      raise EMyException.Create('Duplicate connection definition name!');
    

    这样的代码可以作为您报告的问题的解决方法。我试着描述一下出了什么问题。

    防止连接定义名称重复有什么错?

    RSP-19107 问题嗯,这是一个很好的隐藏。只有当应用程序中包含物理驱动程序模块时,我才能再现该问题 . 预期异常:

    [FireDAC][Stan][Def]-255。定义名称[FBPooled]重复

    当应用程序中不包括物理驱动器模块时,正确提升。如果包含驱动程序模块,则不会引发异常,并将具有重复名称的连接定义添加到内部集合。

    FDManager.AddConnectionDef('DefName', 'FB', Params);
    Params.Values['Database'] := 'C:\MyDatabase.db';
    FDManager.AddConnectionDef('DefName', 'FB', Params);
    

    定义名称的重复检查在 TFD定义。ParamsChanged公司 添加连接Def 方法稍后添加到下面的定义参数中 键,然后引擎等待调用所述 方法

    中的定义设置 添加连接Def

    Definition.Params.BeginUpdate; { ← triggers TFDDefinition.ParamsChanging }
    try
      Definition.Params.SetStrings(Params); { ← assigns the passed parameters }
      Definition.Name := 'DefName'; { ← adds (or sets) the Name key value in Params }
      Definition.Params.DriverID := 'FB'; { ← creates driver specific parameter instance }
    finally
      Definition.Params.EndUpdate; { ← triggers TFDDefinition.ParamsChanged }
    end;
    

    . 它触发驱动程序特定参数实例的创建(例如。 TFDPHYSFB连接参数 参数

    Definition.Params.BeginUpdate; { ← Definition.Params.FUpdateCount += 1 }
    try
      Definition.Params.Free;
      Definition.Params := TDriverSpecificConnectionDefParams.Create;
    finally
      Definition.Params.EndUpdate; { ← Definition.Params.FUpdateCount == 0 }
    end;
    

    参数 FUpdateCount OnChange公司 调用时的事件 并且要应用

    TFD定义。ParamsChanged公司 方法不会由此触发 最后

    在伪代码中解决此问题的可能方法是:

    var
      UpdateCount: Integer;
    begin
      Definition.Params.BeginUpdate; { ← Definition.Params.FUpdateCount == n }
      try
        UpdateCount := Definition.Params.UpdateCount; { ← store the update count }
        Definition.Params.Free;
        Definition.Params := TDriverSpecificConnectionDefParams.Create;
        Definition.UpdateCount := UpdateCount; { ← set the update count for the new instance }
      finally
        Definition.Params.EndUpdate; { ← Definition.Params.FUpdateCount == n }
      end;
    end;
    

    [1] 实际上,如果有任何 驱动程序文件在您的使用列表中;通过放置一个 TFDPhys<DBMS>驱动链接 表单上的组件。