Как я могу обнаружить, что TadoConnection потерял связь с сервером?

Я должен обнаружить, когда компонент TAdoConnection потерял соединение с сервером. Я попытался использовать событие OnDisconnect, но это только стреляет, когда Близкий метод называют, или свойство Connected имеет значение false.

Другая опция, которую я попробовал, использует TTimer и выполняет запрос как это

SELECT 1 RESULT FROM DUAL

в событии OnTimer, ловя любое исключение, которое происходит.

Существует ли более оптимальный вариант обнаружить, что соединение было потеряно?

11
задан mghie 18 February 2010 в 15:51
поделиться

3 ответа

Я вижу таблицу DUAL. Значит, вы используете Oracle :)

Для большинства (всех?) Клиент-серверных СУБД нет другого способа определить, что соединение потеряно, кроме как запросить у СУБД какое-то действие. Причин потери связи очень много. Может быть сбой сети, может быть ..., может быть администратор базы данных отключил БД.

Многие API СУБД, в том числе Oracle OCI, имеют специальные функции, позволяющие проверять связь с СУБД. «Пинг» - это минимально возможный запрос к СУБД. Вышеупомянутый SELECT требует гораздо больше работы, чем такой ping.

Но не все компоненты доступа к данным, включая ADO, позволяют пинговать СУБД, используя вызов ping API СУБД. Затем вам нужно использовать какую-то команду SQL.Итак, приведенный выше SELECT верен для ADO. Другой вариант - BEGIN NULL; КОНЕЦ;. Возможно, он использует меньше ресурсов СУБД (нет необходимости в оптимизаторе, нет необходимости описывать набор результатов и т. Д.).

TTimer в порядке. Запрос должен выполняться в потоке, где используется соответствующее соединение. Хотя не обязательно, но это другой вопрос.

Потенциальная проблема может заключаться в закрытии соединения при потере соединения. Поскольку закрытие соединения может вызвать исключение из-за того, что API СУБД может находиться в состоянии сбоя.

Что-то вроде того ...

11
ответ дан 3 December 2019 в 08:55
поделиться

@Dimitry, ответ очень хорош. Если для вашего приложения важно знать, потеряно ли соединение, используйте подход TTimer (с минимальными операциями).

Если вы просто хотите знать, когда оператор не работает из-за «потери связи», вы можете использовать событие Application.OnException и проверить свойства Exception.

В качестве примера я сделал следующий код, используя компонент ApplicationEvents. Это всего лишь черновик с идеей, не пригодный для производства.

uses
  ComObj;

procedure TForm2.ApplicationEvents1Exception(Sender: TObject; E: Exception);
var
  EO: EOleException;
begin
  if E is EOLEException then
  begin
    EO := EOleException(E);
    //connection error (disconnected)
    if EO.ErrorCode = E_FAIL then
    begin
      try
        try
          ADOConnection1.Close;
        except
          ;
        end;
        ADOConnection1.Open;
        ShowMessage('Database connection failed and re-established, please retry!');
      except
        on E:Exception do
          ShowMessageFmt('Database connection failed permanently.  '
            + 'Please, retry later'#13'Error message: %s', [E.Message]);
      end;
    end
    else
      ShowMessage(E.Message + ' ' + IntToStr(EO.ErrorCode));
  end
  else
    ShowMessage(E.ClassName + #13 + E.Message);
end;

С уважением.

3
ответ дан 3 December 2019 в 08:55
поделиться

Это одна из причин отказаться от ADO и использовать DBX. Архитектура Ado основана на серверном курсоре, и это необходимо для того, чтобы не терять соединение с сервером в любое время. Если при некоторых обстоятельствах соединение будет потеряно, оно не сможет снова установить соединение. С другой стороны, DBX может восстановить соединение почти всегда из-за своей отключенной архитектуры.

-1
ответ дан 3 December 2019 в 08:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: