使用 DECIMAL 类型打开 MSSQL TFDTable:'Connection is busy with results for another hstmt' when FetchOptions.Items contains fiMeta

Opening MSSQL TFDTable with DECIMAL types: 'Connection is busy with results for another hstmt' when FetchOptions.Items contains fiMeta

如果我打开包含 DECIMAL/NUMERIC 数据类型的 MSSQL table,我会收到 'Connection is busy with results for another hstmt' 错误。 跟踪 FireDAC 代码,我看到它在获取元信息时发生了这种情况,请参阅堆栈跟踪:

我知道错误是关于 multiple open connections to the ODBC database,可能是因为数据集没有一次检索所有数据(并保持打开状态),但我所做的 不是 理解是:

我们在 TFDConnection 上明确设置了 FetchOptions.Mode := fmAll(作为唯一的提取选项)并且没有覆盖 TFDTable 中的选项。

这是一个小型测试应用程序,我(目前)对代码中的 [fiMeta] 排除不满意 table:我现在必须重新测试我们的主要应用程序因为这个排斥而摔倒。

还有其他方法可以解决这个问题吗?
在我的 TFDConnection 中启用 MARS 会有帮助吗?我该怎么做?

我已经使用 TFDMoniFlatFileClientLink 来检查有关 MARS 的情况。我的代码是否使用运行时赋值 TFDConnection.DriverName := 'MSSQL' 我在设计时设置了 DriverName(然后 Params.MARS 出现并被选中),这就是我所看到的在跟踪中:

SQLDriverConnect [szConnStr="DRIVER=SQL Server;UID=test;PWD=****;Server=VS2003-2008;Database=test"]

如果我明确添加 Params.Add('MARS=No'); 这将更改为:

SQLDriverConnect [szConnStr="DRIVER=SQL Server;UID=test;PWD=****;Server=VS2003-2008;Database=test;MARS_Connection=No"]

...这让我想知道 MARS 是否处于活动状态。

如果我明确添加 Params.Add('MARS=Yes'); 这将更改为:

SQLDriverConnect [szConnStr="DRIVER=SQL Server;UID=test;PWD=****;Server=VS2003-2008;Database=test;MARS_Connection=Yes"]

...但问题并没有消失

背景资料:

测试table:

CREATE TABLE dbo.TESTDEC
(
  TT_ID INTEGER NOT NULL CONSTRAINT TT_C0_TEST DEFAULT 0,
  TT_DEC DECIMAL NULL,
  TT_NUM NUMERIC NULL,
  TT_DEC5_0 DECIMAL(5,0) NULL,
  TT_NUM5_0 NUMERIC(5,0) NULL,
  TT_DEC5_3 DECIMAL(5,3) NULL,
  TT_NUM5_3 NUMERIC(5,3) NULL,
  TT_DEC15_0 DECIMAL(15,0) NULL,
  TT_NUM15_0 NUMERIC(15,0) NULL,
  TT_DEC15_3 DECIMAL(15,3) NULL,
  TT_NUM15_3 NUMERIC(15,3) NULL,
  TT_DEC25_0 DECIMAL(25,0) NULL,
  TT_NUM25_0 NUMERIC(25,0) NULL,
  TT_DEC25_3 DECIMAL(25,3) NULL,
  TT_NUM25_3 NUMERIC(25,3) NULL,
  TT_DEC35_0 DECIMAL(35,0) NULL,
  TT_NUM35_0 NUMERIC(35,0) NULL,
  TT_DEC35_3 DECIMAL(35,3) NULL,
  TT_NUM35_3 NUMERIC(35,3) NULL
);

insert into dbo.testdec values(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
insert into dbo.testdec values(2,2,2,2,2,2.22,2.22,2,2,2.22,2.22,2,2,2.22,2.22,2,2,2.22,2.22);
insert into dbo.testdec values(3,33333,33333,33333,33333,33.333,33.333,33333333333,33333333333,33333333333.333,33333333333.333,33333333333,33333333333,33333333333.333,33333333333.333,33333333333,33333333333,33333333333.333,2.22);

完整示例程序源
如果需要,将 FDConnection.Params.Add('MARS=Yes');FDConnection.FetchOptions.Mode := fmAll; 添加到 FormShow;他们没有区别。

.dpr 文件:

  program BrowseSQLDecimal;

  uses
    Forms,
    uTest in 'uTest.pas' {FrmTest};

  {$R *.res}

  begin
    Application.Initialize;
    Application.Title := 'Browse DB';
    Application.CreateForm(TFrmTest, FrmTest);
    Application.Run;
  end.

表格.pas:

unit uTest;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Vcl.StdCtrls,

  FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
  FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.MSSQL,
  FireDAC.Phys.MSSQLDef, FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS,
  FireDAC.DApt.Intf, FireDAC.DApt, FireDAC.Comp.DataSet,
  FireDAC.Comp.Client, FireDAC.Moni.Base, FireDAC.Moni.FlatFile;

type
  TFrmTest = class(TForm)
    Button1: TButton;
    Button2: TButton;
    FDConnection: TFDConnection;
    TableTT_ACT: TFDTable;
    TableTESTDEC: TFDTable;
    procedure FormShow(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
  public
  end;

var
  FrmTest: TFrmTest;

implementation

{$R *.dfm}

procedure TFrmTest.Button1Click(Sender: TObject);
begin
   TableTT_ACT.TableName := 'TT_ACT';
   TableTT_ACT.Open;
end;

procedure TFrmTest.Button2Click(Sender: TObject);
begin
   TableTESTDEC.TableName := 'TESTDEC';
   TableTESTDEC.Open;
end;

procedure TFrmTest.FormShow(Sender: TObject);
begin
   FDConnection.Open;
end;

end.

表格.dfm:

object FrmTest: TFrmTest
  Left = 0
  Top = 0
  Caption = 'Test'
  ClientHeight = 276
  ClientWidth = 560
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 32
    Top = 24
    Width = 97
    Height = 25
    Caption = 'Open TT_ACT'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 32
    Top = 56
    Width = 97
    Height = 25
    Caption = 'Open TESTDEC'
    TabOrder = 1
    OnClick = Button2Click
  end
  object FDConnection: TFDConnection
    Params.Strings = (
      'MonitorBy=FlatFile'
      'DriverID=MSSQL'
      'User_Name=test'
      'Password=test'
      'Database=test'
      'Server=VS2003-2008')
    Left = 224
    Top = 24
  end
  object TableTT_ACT: TFDTable
    Connection = FDConnection
    Left = 72
    Top = 149
  end
  object TableTESTDEC: TFDTable
    Connection = FDConnection
    Left = 72
    Top = 213
  end
end

这是驱动程序问题。

我的 Windows 7 开发机器 只有 有(默认?)32 位 ODBC 驱动程序,名为 SQL Server,版本 6.01.7601.17514

如果我安装更高版本的本机客户端或 ODBC 驱动程序,则没有问题。

另一种解决方法(如问题中所述)是为 TFDTable 更改 FetchOptions.Items := FetchOptions.Items - [fiMeta];(不要为 TFDConnection 更改,其他数据库不需要这样做使用该连接的组件)。

备注

  1. 测试:

  2. 这不适用于 Microsoft ODBC Driver 17 for SQL Server,因为 FireDAC 代码尚未检测到该驱动程序。 TFDPhysODBCDriverBase.FindBestDriver 对驱动程序的名称进行字符串比较,代码中的最新硬连线 SQL 服务器驱动程序字符串是 ODBC DRIVER 13 FOR SQL SERVERSQL 服务器本机客户端 11.0. 1,2

  3. 使用这些下载的 x64 版本;他们将(也)安装 32 位 ODBC 驱动程序。

  4. 这是关于驱动机器上安装的运行程序,即不管数据库服务器上安装了什么。

  5. 我还有一个问题:这实际上不是一个 FireDAC 错误吗?为什么 FireDAC 代码执行 TFDPhysCommandAsyncOpen(参见有问题的堆栈转储)而不是同步执行?

1. SQL Server Native Client 9 也不是 出席
2. Request done