使用DECIMAL类型打开MSSQL TFDTable:当FetchOptions.Items包含fiMeta

时间:2018-04-25 11:54:36

标签: sql-server delphi firedac delphi-10.2-tokyo

如果我打开一个包含DECIMAL / NUMERIC数据类型的MSSQL表,我会得到'连接正忙于另一个hstmt的结果'错误。 跟踪FireDAC代码我发现当它获取元信息时会发生这种情况,请参阅堆栈跟踪:

enter image description here

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

  • 为什么只有包含DECIMAL字段的表才会发生?其他表工作正常,小或大,我可以在多个选项卡上同时打开多个网格,甚至可以编辑数据。
  • 为什么元数据相关?如果我FetchOptions.Items := FetchOptions.Items - [fiMeta];,则不会发生错误。这是FireDAC中的错误吗?

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

这是一个小型测试应用,我(目前)对代码中的[fiMeta]排除不满意:我现在必须重新测试我们的主要应用,因为这个排除没有任何遗漏。

还有其他方法可以解决此问题吗?
会在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"]

... 但问题不会消失

背景资料:

  • 根据Browsing Tables (FireDAC)我们在实时数据窗口模式下操作,因为CachedUpdatesFetchOptions.UniDirectionalFetchOptions.CursorKind具有默认值
  • Delphi Tokyo 10.2.3,Win 32 app
  • 必须支持SQL Server 2005及更高版本
  • 使用或不使用dtBCDdtFmtBCD字段类型
  • 的映射规则时会发生这种情况
  • 有一个关于此的Embarcadero forums threadnewsgroup thread,但两者都已消失。
  • DelphiPraxis post here,没有解决方案。

测试表:

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

1 个答案:

答案 0 :(得分:0)

这是一个驱动程序问题。

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

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

另一种解决方法(如问题中所述)将更改public String daysNameOfWeek(String inputDate){ DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.UK); try { Date date = df.parse(inputDate.trim()); SimpleDateFormat outFormat = new SimpleDateFormat("EEEE"); daysName = outFormat.format(date); } catch (ParseException e) { e.printStackTrace(); } return daysName; } 的{​​{1}}(不要为FetchOptions.Items := FetchOptions.Items - [fiMeta];执行此操作,它不是使用该连接的其他数据库组件的必要性。)

备注

  1. 经过测试:

  2. 这不适用于Microsoft ODBC Driver 17 for SQL Server,因为FireDAC代码尚未检测到该驱动程序。 TFDTable对驱动程序的名称进行字符串比较,代码中最新的硬连线SQL Server驱动程序字符串为 ODBC DRIVER 13 FOR SQL SERVER SQL SERVER NATIVE CLIENT 11.0 1,2

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

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

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

  6. 1。 SQL Server Native Client 9都不是Request done  目前
    2. SQL Fiddle Demo