PostgreSQL停止时永远不会触发TFDConnection.OnRecover

时间:2019-03-11 13:56:05

标签: delphi

我使用Recovering Connection (FireDAC)中所述的Firedac连接恢复功能,并且在Delphi XE5上一切正常。

我安装了Delphi社区版本10.2、10.3和10.3.1进行迁移测试,发现数据库重新连接功能无法正常工作。

使用场景:

  • Windows 10专业版X64 1803
  • Delphi 10.2 / 10.3 / 10.3.1
  • PostgreSQL 9.5.16 x64

重现此问题的步骤:

1-创建一个新的VCL应用程序;

2-在Form1上,删除组件TFDConnection,TFDPhysPgDriverLink,TFDGUIxWaitCursor,TFDQuery和TButton;

3-为TFDPhysPgDriverLink的PostgreSQL和vendorlib libpq.dll的连接参数配置TFDConnection;

4-按照Recovering Connection (FireDAC)中的说明配置TFDConnection;

5-在TButton OnClick事件中,放置以下内容:

qry1.Close;
qry1.Open ('select 1');

6-在Recovering Connection (FireDAC)中所述,在TFDConnection的OnRecover事件中放置以下代码:

var
  iRes: Integer;
begin
  iRes: = MessageDlg ('Connection is lost. Offline - yes, Retry - ok, Fail - Cancel', mtConfirmation, [mbYes, mbOK, mbCancel], 0);
  case iRes of
    mrYes: AAction: = faOfflineAbort;
    mrOk: AAction: = faRetry;
    mrCancel: AAction: = faFail;
  end;
// Log ('Connection is recovering');

7-运行应用程序;

8-单击一次TButton;

9-重新启动PostgreSQL服务或禁用/重新启用网络适配器;

10-再次单击TButton,请注意TFDConnection组件未触发OnRecover事件,而是显示以下错误:

  

[FireDAC] [Phys] [PG] [libpq]服务器关闭了连接   意外地这可能意味着服务器异常终止   在处理请求之前或期间。

再次单击TButton,每次都会显示另一个错误:

  

[FireDAC] [Phys] [PG] [libpq]与服务器无连接

预先感谢您对此进行审查。

这个问题与我的情况相似,但它是针对Delphi 10: When PostgreSQL stops TFDConnection.Connected remains True

1 个答案:

答案 0 :(得分:0)

我根据RSP-23958向Embarcadero质量中心报告了此问题,并且对该错误进行了认可。有人叫德米特里(Dmitry)回答说,该问题将在Delphi 10.3的更新2中解决。

在RSP-23958中,附带了一个解决问题的修补程序,如果您具有带有Firedac源代码的Dephi,而未发布Delphi 10.3更新2,则可以使用它。

解决方法如下:

Index: runtime/data/firedac/FireDAC.Phys.PGWrapper.pas
===================================================================
--- runtime/data/firedac/FireDAC.Phys.PGWrapper.pas (revision 95224)
+++ runtime/data/firedac/FireDAC.Phys.PGWrapper.pas (revision 95225)
@@ -1109,7 +1109,9 @@
      FDStrLike(sLCMessage, 'password authentication failed for user "%"') then
     eKind := ekUserPwdInvalid
   else if (Pos('connection refused', sLCMessage) <> 0) or
-          (Pos('could not connect to server', sLCMessage) <> 0) then
+          (Pos('could not connect to server', sLCMessage) <> 0) or
+          (Pos('server closed the connection unexpectedly', sLCMessage) <> 0) or
+          (Pos('no connection to the server', sLCMessage) <> 0) then
     eKind := ekServerGone
   else
     eKind := ekOther;