【发布时间】:2020-08-26 11:55:08
【问题描述】:
我有一个使用 ADO 组件的 Delphi 项目,目前是 SQL Server 2017。
我注意到 Microsoft has 3 possible providers ,Microsoft 建议对新项目使用“第 3 代”。
SQLOLEDB (Generation 1) works
SQLNCLI11 (Generation 2) does NOT work
MSOLEDBSQL (Generation 3) does NOT work
为了测试“第 3 代”,我将连接字符串中的提供程序从 SQLOLEDB 更改为 MSOLEDBSQL。
但是,我注意到如果在事务中使用 TAdoCommand 添加列,然后设置超时,则会导致问题。执行后设置超时时会发生错误。
这是一个重现问题的示例:
uses
ADODB;
procedure TForm2.Button1Click(Sender: TObject);
const
// SQLOLEDB (Generation 1) works
// SQLNCLI11 (Generation 2) does NOT work
// MSOLEDBSQL (Generation 3) does NOT work
SqlServerProvider= 'MSOLEDBSQL';
var
mConnection: TADoConnection;
command: TadoCommand;
begin
mConnection := TAdoConnection.Create(nil);
try
mConnection.ConnectionString := 'Provider='+SqlServerProvider+';Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=CORAMASTER_1;Data Source=SHS\HS2017,49010';
mConnection.KeepConnection := true;
mConnection.LoginPrompt := false;
mConnection.Connected := true;
mConnection.BeginTrans;
command := TADOCommand.Create(nil);
try
command.Connection := mConnection;
command.ParamCheck := false;
command.CommandText := 'alter table TESTTABLE add TESTCOLUMN int;';
command.CommandTimeout := 100;
command.Execute;
// If I set "CommandTimeout" here, I get the following error:
// Spaltennamen müssen in jeder Tabelle eindeutig sein. Der Spaltenname "..." wurde in der ...-Tabelle mehrmals angegeben.
// Translated: Column names must be unique in each table. The column name "..." appears multiple times.
// The error happens with provider MSOLEDBSQL (Generation 3) and SQLNCLI11 (Generation 2), but SQLOLEDB (Generation 1) works
command.CommandTimeout := 50; // ERROR!
finally
FreeAndNil(command); // Note: In the real project, I am keeping the command object. This is just for the example
end;
mConnection.RollbackTrans;
finally
FreeAndNil(mConnection);
end;
end;
我做错了什么?这是 ADO 组件中的错误吗?
编辑:这是使用 Microsoft SQL Server Profiler 的 SQL Server 跟踪日志:
当我执行第二个“SetTimeout”命令时,SQL 服务器执行命令exec [sys].sp_describe_first_result_set N'alter table TESTTABLE add TESTCOLUMN int;',NULL,1,这显然会导致错误。我不知道为什么会调用 sp_describe_first_result_set 以及如何防止它...
【问题讨论】:
-
哪个 Delphi 版本? Istr 在 很久 之前(大约 D3/D5 时代)在 Delphi 中设置 ADO 超时存在问题。
-
我使用的是 Delphi 2007(我知道它很旧,但不幸的是,我依赖无法更新的旧 VCL/框架)
-
为什么要在命令执行后设置CommandTimeout?
-
我对那个 Delphi 一无所知 - 但我看到一个连接已创建但从未打开。很难相信
mConnection.Connected := true;实际上打开了连接。没有 CATCH 的 TRY 是没有意义的。 -
@SMor:恐怕你的两个cmets都不正确。在 Delphi 中,将 Connected 属性设置为 True 是打开连接的一种完全有效的方式(实际操作发生在属性的设置器中),它有两个
try构造,try ... except用于异常处理和 @987654335 @ 用于资源保护。
标签: sql-server delphi ado