Microsoft AlwaysOn отказоустойчивое решение и Delphi

Я пытаюсь заставить приложение Delphi работать с решением AlwaysOn. Я нашел в Google, что я должен использовать MultiSubnetFailover=True в строке подключения.

Приложение скомпилировано в Delphi XE3 и использует TADOConnection,

Если я использую Provider=SQLOLEDB в строке подключения приложение запускается, но выглядит MultiSubnetFailover=True не имеет никакого эффекта

Если я использую Provider=SQLNCLI11 (Я обнаружил в Google, что OLEDB не поддерживает решение AlwaysOn, и мне приходится использовать собственный клиент SQL) Я получаю недопустимый атрибут при попытке открыть соединение.

Строка подключения:

Provider=SQLOLEDB.1;Password="password here";Persist Security Info=True;User ID=sa;Initial Catalog="DB here";Data Source="SQL Instance here";MultiSubnetFailover=True

Нужно ли переходить на более новую версию в Delphi, чтобы использовать это решение для восстановления после сбоя, или я что-то упускаю в строке подключения?

1 ответ

Решение

В настоящее время я использую XE2 с SQL Server AlwaysOn. Если вы прочитаете документацию, то увидите, что события устойчивости AlwaysOn приведут к сбою подключения к базе данных, и вам нужно будет инициировать новое.

Если приложение SqlClient подключено к базе данных AlwaysOn, при которой происходит сбой, исходное соединение разрывается, и приложение должно открыть новое соединение, чтобы продолжить работу после отработки отказа.

Я справился с этим с помощью простого способа переопределения компонента TAdoQuery моей собственной версией, которая повторяет соединение после сбоя соединения. Это может быть неправильный способ сделать это, но это, безусловно, работает. Он переопределяет методы, вызываемые для открытия (если запрос возвращает набор результатов) или выполняет SQL (в противном случае), и в случае сбоя из-за потери соединения повторяется попытка (но только один раз). Я тщательно проверил это в отношении переключателей AlwaysOn, и он надежно работает для нашей конфигурации. Он также будет реагировать на любые другие события потери соединения и, следовательно, будет иметь дело с некоторыми другими причинами сбоя запросов. Если вы используете компонент, отличный от TAdoQuery, вам необходимо создать аналогичные переопределения для этого компонента.

Возможно, с этим можно справиться и другими способами, но я перестал искать альтернативы, как только нашел то, что сработало. Возможно, вы захотите привести в порядок утверждение использования, поскольку оно явно включает в себя некоторые вещи, которые не нужны. (Просто глядя на этот код, я хочу уйти и реорганизовать дублирование кода)

unit sptADOQuery;

interface

uses
  Windows, Messages, SysUtils, Classes, Db, ADODB;

type
  TsptADOQuery = class(TADOQuery)
  protected
    procedure SetActive(Value: Boolean); override;
  public
    function ExecSQL: Integer;   // static override
  published
  end;

procedure Register;

implementation

uses ComObj;

procedure Register;
begin
  RegisterComponents('dbGo', [TsptADOQuery]);
end;

procedure TsptADOQuery.SetActive(Value: Boolean);
begin
  try
    inherited SetActive(Value);
  except
    on e: EOleException do
    begin
      if (EOleException(e).ErrorCode = HRESULT($80004005)) then
      begin
        if Assigned(Connection) then
        begin
          Connection.Close;
          Connection.Open;
        end;
        inherited SetActive(Value);   // try again
      end
      else raise;
    end
    else raise;
  end;
end;

function TsptADOQuery.ExecSQL: Integer;
begin
  try
    Result := inherited ExecSQL;
  except
    on e: EOleException do
    begin
      if (EOleException(e).ErrorCode = HRESULT($80004005)) then
      begin
        if Assigned(Connection) then
        begin
          Connection.Close;
          Connection.Open;
        end;
        Result := inherited ExecSQL;   // try again
      end
      else raise;
    end
    else raise;
  end;
end;

end.
Другие вопросы по тегам