Открытие MSSQL TFDTable с типами DECIMAL: «Соединение занято результатами для другого hstmt», когда FetchOptions.Items содержит fiMeta - PullRequest
0 голосов
/ 25 апреля 2018

Если я открываю таблицу MSSQL, содержащую типы данных DECIMAL / NUMERIC, я получаю сообщение «Соединение занято с результатами для другого hstmt».Трассировка кода FireDAC Я вижу, что это происходит при получении метаданных, см. Трассировку стека:

enter image description here

Я понимаю, что ошибка составляет около несколько открытых соединений с базой данных ODBC , возможно, потому что набор данных не извлекает все данные одновременно (и остается открытым), но я не понимаю:

  • Почему это происходит только с таблицами, содержащими поля DECIMAL?Другие таблицы работают нормально, маленькие или большие, я могу одновременно открывать множество таблиц на нескольких вкладках, даже редактировать данные.
  • Почему метаданные актуальны?Если я сделаю FetchOptions.Items := FetchOptions.Items - [fiMeta];, ошибок не будет.Это ошибка в FireDAC?

У нас явно есть FetchOptions.Mode := fmAll (в качестве единственной опции выборки) для TFDConnection и нет переопределения параметров в TFDTable.

Это небольшое тестовое приложение, и меня (в настоящее время) не устраивает исключение [fiMeta] в коде: теперь мне придется повторно тестировать наши основные приложения, в которых ничего не падает из-за этого исключения.

Есть ли другие способы решения этой проблемы? Поможет ли включение MARS в моем TFDConnection справке?Как мне это сделать?

Я использовал 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"]

... , но проблема не исчезнет .

Справочная информация:

  • Согласно Просмотр таблиц (FireDAC) мы работаем в режиме окна данных в реальном времени, потому что CachedUpdates, FetchOptions.UniDirectional и FetchOptions.CursorKind имеют значения по умолчанию
  • Delphi Tokyo 10.2.3, Win 32приложение
  • должен поддерживать SQL Server 2005 и более поздние версии
  • Это происходит с использованием правил отображения для полей типа dtBCD и dtFmtBCD или без них
  • Embarcadero ветка форумов и ветка новостной группы об этом, но оба пропали.
  • DelphiPraxis пост здесь ,нет решения.

Тестовый стол:

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 голосов
/ 09 мая 2018

Это проблема с драйвером.

Мой компьютер для разработки под Windows 7 только имеет (по умолчанию?) 32-разрядный драйвер ODBC с именем SQL Server , версия 6.01.7601.17514

Если я установлю более поздний собственный клиент или драйвер ODBC, проблем не будет.

Другой обходной путь (как упомянуто в вопросе) - изменить FetchOptions.Items := FetchOptions.Items - [fiMeta]; для TFDTable(не делайте это для TFDConnection, это не обязательно для других компонентов базы данных, использующих это соединение).

Примечания :

  1. Протестировано с:

  2. Это не работает с Microsoft ODBC Driver 17 для SQL Server , поскольку код FireDAC еще не обнаруживает этот драйвер.TFDPhysODBCDriverBase.FindBestDriver выполняет сравнение строк для имен драйверов и последних строк драйвера аппаратного обеспечения SQL Server в коде: ODBC DRIVER 13 FOR SQL SERVER и SQL SERVER NATIVE CLIENT 11.0 . 1,2

  3. Используйте 64-разрядные версии этих загрузок;они (также) установят 32-разрядные драйверы ODBC.

  4. Это касается драйверов, установленных на компьютере, на котором выполняется программа, т.е. независимо от того, что установлено на серверах баз данных.

  5. У меня остается один вопрос: не является ли это ошибкой FireDAC, на самом деле?Почему код FireDAC выполняет TFDPhysCommandAsyncOpen (см. Рассматриваемый дамп стека) вместо того, чтобы делать это синхронно?

1.Также отсутствует собственный клиент SQL Server 9 2. Запрос выполнен

...