微软AlwaysOn故障转移解决方案和Delphi

6
我正在尝试制作一个与AlwaysOn解决方案配合使用的Delphi应用程序。我在Google上发现,我必须在连接字符串中使用MultiSubnetFailover=True
该应用程序是在Delphi XE3中编译,并使用TADOConnection
如果我在连接字符串中使用Provider=SQLOLEDB,则应用程序可以启动,但似乎MultiSubnetFailover=True没有效果。
如果我使用Provider=SQLNCLI11(我在Google上发现OLEDB不支持AlwaysOn解决方案,我必须使用SQL Native客户端),则在尝试打开连接时会出现无效属性。
连接字符串如下:
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版本才能使用此故障转移解决方案,或者是连接字符串中缺少了什么?


你在连接字符串中写入了 SQLOLEDB.1,但却声称需要使用本地客户端 SQLNCLI11 作为 Provider,这是一个拼写错误吗? 这可能解释了无效属性错误... - TLama
1
你是对的。看起来不支持OLEDB,因此必须使用SQL Native Client,它具有不同的连接字符串语法(http://www.connectionstrings.com/sql-server-native-client-11-0-oledb-provider/)。 - Tiberius Cocarlea
1个回答

7

我目前正在使用XE2和SQL Server AlwaysOn。如果你阅读文档,你会发现AlwaysOn的韧性事件会导致数据库连接失败,你需要启动一个新连接。

如果SqlClient应用程序连接到一个发生故障转移的AlwaysOn数据库,原始连接将被中断,应用程序必须打开一个新连接才能在故障转移后继续工作。

我通过简单地重写TAdoQuery组件来处理这个问题,以便在连接失败后重试连接。这可能不是正确的做法,但它确实起作用。它重写了打开(如果查询返回结果集)或执行SQL(否则)时调用的方法,并且如果由于连接丢失错误而出现故障,则尝试再次连接(但仅限一次)。我对AlwaysOn切换进行了大量测试,针对我们的配置它可以可靠地工作。它还会对任何其他连接丢失事件做出反应,因此可以解决一些其他导致查询失败的原因。如果你使用的是除TAdoQuery之外的组件,你需要为那个组件创建类似的重写。

可能有其他方法来处理这个问题,但我一旦找到了可行的解决方案就停止了寻找替代方案。你可能想整理一下uses语句,因为它明显包括一些不需要的东西。(看着这段代码让我想去重构一下代码重复部分)

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.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接