Microsoft AlwaysOn 故障转移解决方案和 Delphi
Microsoft AlwaysOn failover solution and 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 上升级到较新的版本才能使用此故障转移解决方案,或者我在连接字符串中缺少什么?
我目前正在使用 XE2 和 SQL Server AlwaysOn。如果您阅读文档,您会看到 AlwaysOn 弹性事件会导致您的数据库连接失败,您需要启动一个新连接。
If a SqlClient application is connected to an AlwaysOn database that
fails over, the original connection is broken and the application must
open a new connection to continue work after the failover.
我已经通过用我自己的版本覆盖 TAdoQuery 组件的简单权宜之计来处理这个问题,该版本在连接失败后重试连接。这可能不是执行此操作的正确方法,但它确实有效。它所做的是覆盖为打开而调用的方法(如果查询 returns 结果集)或执行 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(004005)) 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(004005)) 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.
我正在尝试制作一个 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 上升级到较新的版本才能使用此故障转移解决方案,或者我在连接字符串中缺少什么?
我目前正在使用 XE2 和 SQL Server AlwaysOn。如果您阅读文档,您会看到 AlwaysOn 弹性事件会导致您的数据库连接失败,您需要启动一个新连接。
If a SqlClient application is connected to an AlwaysOn database that fails over, the original connection is broken and the application must open a new connection to continue work after the failover.
我已经通过用我自己的版本覆盖 TAdoQuery 组件的简单权宜之计来处理这个问题,该版本在连接失败后重试连接。这可能不是执行此操作的正确方法,但它确实有效。它所做的是覆盖为打开而调用的方法(如果查询 returns 结果集)或执行 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(004005)) 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(004005)) 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.