Page 1 of 1

Reconnect problem

Posted: Thu 10 Dec 2015 12:54
by Traptak
Hello,

I have problem with session reconnect functionality. The LocalFailower property for TOraSession instance has value True. But OnConnectionLost event is not executed when an exception ORA-3135 (connection lost contact) It is because this exception is not treated as FatalError and then in TCustomDAConnection.DoError procedure Reconnect flag has always value False. When Reconnect flag has value False, then reconnect functionality is never started.

Is it a bug? Is it corrected in current version of ODAC? Now I'm using version 9.3.10 of ODAC.

best regards
Adam Siwon

Re: Reconnect problem

Posted: Mon 14 Dec 2015 10:34
by AlexP
Hello,

Thank you for the information. We will add this error to the list of critical errors.

Re: Reconnect problem

Posted: Sun 20 Dec 2015 21:39
by Traptak
Hello,

I have tried to use reconnect mechanism but it does not works when to the TOraSession component are connected prepared queries. Why prepared queries are not supported by reconnection mechanism?

Re: Reconnect problem

Posted: Tue 22 Dec 2015 10:22
by AlexP
This is because we can't call Unprepare first and then prepare all DataSets again.

Re: Reconnect problem

Posted: Fri 15 Jan 2016 22:07
by Traptak
Hi,

I agree that you can't from components level unprepare and then prepare all datasets. But I think I can do it manually in my application according to my needs. I made some changes in ODAC to prepare this mechanism. The only thing which I need are two events which are fired while reconnect process. The first one is event called OnBeforeReconnect. It is intended to inform application that reconnect proces was started. Event type declarations looks like:

Code: Select all

  TBeforeReconnectEvent = procedure (Sender: TObject; const AReconnectAttempt: Integer;
    const AErrorComponent: TObject) of object;
this event is declared in TCustomDAConnection class and published in TOraSession. Event is fired from DoError procedure:

Code: Select all

procedure TCustomDAConnection.DoError(E: Exception; var Fail, Reconnect, Reexecute: boolean;
  ReconnectAttempt: integer; var ConnLostCause: TConnLostCause);
var
  i: integer;
  FatalError: boolean;
  RetryMode: TRetryMode;
begin
  ConnLostCause := clUnknown;
  TDASQLMonitorClass(SQLMonitorClass).DBError(EDAError(E));

  FatalError := EDAError(E).IsFatalError;

  if FatalError then begin

    with EDAError(E) do begin
      ConnLostCause := DetectConnLostCause(Component);

      Reconnect :=
        (Connected
        or ((ReconnectAttempt > 0) and Options.LocalFailover)       // After first abortive attempt Connected = False
        or (ConnLostCause = clConnect) and Options.DisconnectedMode)  // For disconnect mode TODO:
        and (IsFailOverAllowed or (ConnLostCause = clConnectionApply));

      if Reconnect then
      begin
          // Wywołanie zdarzenia umożliwiającego preparację zbiorów danych przed wykonaniem ponownego połączenia.
        if Assigned(FOnBeforeReconnect) then
          FOnBeforeReconnect(Self, ReconnectAttempt, Component);
...
The second event was named OnAfterRestoreFailOver and is also declared in TCustomDAConnection class. This event is fired from RestoreAfterFailOver procedure. After changes procedure looks like:

Code: Select all

procedure TCustomDAConnection.RestoreAfterFailOver;
var
  i: integer;
begin
  for i := 0 to FTransactions.Count - 1 do
    FTransactions[i].Restore;
  if Assigned(FOnAfterRestoreFailOver) then
    FOnAfterRestoreFailOver(Self);
end;
This are whole changes in ODAC components. Now what I should to do in application:
1. In OnBeforeReconnect event at first I'm marking all prepared datasets as unprepared using code:

Code: Select all

      
     if TCustomDADataSetFriend(lDataSet).Data.Prepared then
        TCustomDADataSetFriend(lDataSet).Data.Prepared := False;
Its it required to run reconnect proces in ODAC components. I must to mark dataset as unprepared. Calling regular Unprepare method will cause memory leak problems. I know it is not elegant solution, but I had no choice.
In this event I'm also collecting whole prepared dataset in the list which is used in second event.

2. In OnAfterRestoreFailover I'm preparing back again whole datasets which was marked as unprepared in OnBeforeReconnect event. I'm doing this task using code:

Code: Select all

   
        TCustomDADataSetFriend(lItem.Component).Data.Prepared := True;
        TCustomDADataSet(lItem.Component).UnPrepare;
        TCustomDADataSet(lItem.Component).Prepare;
But this is my scenario. I think it could be done in different way. Datasets could be prepared again just before reopening or some other simillar solutions could be used.

The only condition is: components should allow to do this actions.

What do you think about described method?

Re: Reconnect problem

Posted: Wed 20 Jan 2016 09:47
by AlexP
These both methods are virtual, and you can create a descendant and add the needed functionality.

P.S. We are not going to add these changes yet.