Не одинаковое поведение Table-Valued Parameters

Обсуждение возникших проблем, предложений и ошибок SDAC компонентов
vso
Сообщения: 39
Зарегистрирован: Чт 24 янв 2013 11:08

Не одинаковое поведение Table-Valued Parameters

Сообщение vso » Пн 26 авг 2013 07:41

Добрый день!

Есть связь TMSQuery -> TMSUpdateSQL -> TMSStoredProc.

Есть два варианта кода.
Вариант 1.

Код: Выделить всё

TMSStoredProc.PrepareSQL;
TMSStoredProc.Params.ParamByName('Table').AsTable := TMSTableData.Table;
TMSQuery.Post;
Вариант 2

Код: Выделить всё

TMSStoredProc.PrepareSQL;
TMSStoredProc.Params.ParamByName('Table').AsTable := TMSTableData.Table;
TMSStoredProc.ExecProc;
Так вот если использовать вариант 1, то возникает ошибка. SQL возвращает "Недопустимый тип параметра".
Если же использовать Вариант 2, то все работает, но тогда состояние TMSQuery, после выполнения TMSStoredProc так же в dsInsert или dsEdit.
А надо бы чтобы изменилось и отработало свойство Refresh.

Подскажите как быть?

vso
Сообщения: 39
Зарегистрирован: Чт 24 янв 2013 11:08

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение vso » Вт 27 авг 2013 08:28

Попробовал перенести вызов процедуры в TMSQuery, написав:

Код: Выделить всё

exec spAddVolume :LINK_REPORTS READONLY, :ID_VOLUME, :NUMBER, :TITLE, :VERSION, :REF_TYPE, :SHORTNAME, :LONGNAME, :REF_BUILDING, :NUM_REVISION
но получаю ошибку:

Код: Выделить всё

Возвращающий табличное значение параметр "@P1" должен быть объявлен как READONLY.
хотя в процедуре все прописано:

Код: Выделить всё

ALTER PROCEDURE [dbo].[spAddVolume]
  @LINK_REPORTS dbo.LinkReports READONLY,
  @ID_VOLUME    INT,
  @NUMBER       VARCHAR(50),
  @TITLE        VARCHAR(510),
  @VERSION      INT,
  @REF_TYPE     INT,
  @SHORTNAME    VARCHAR(255),
  @LONGNAME     VARCHAR(255),
  @REF_BUILDING INT,
  @NUM_REVISION VARCHAR(20)
AS

Alexp
Devart Team
Сообщения: 349
Зарегистрирован: Пн 27 дек 2010 10:34

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение Alexp » Вт 27 авг 2013 11:31

Добрый день,

Пожалуйста пришлите небольшое приложение воспроизводящее проблему на alexp*devart*com, а также скрипты для создания объектов БД.

P.S. При Вызове TMSStoredProc.ExecProc связанный с этим компонентом DataSet не изменит своего состояния, состояние меняться только после вызова Post

Alexp
Devart Team
Сообщения: 349
Зарегистрирован: Пн 27 дек 2010 10:34

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение Alexp » Чт 29 авг 2013 12:19

Добрый день,

Спасибо, я получил Ваш пример. Это корректное поведение, так как если для добавления/обновления данных в MSQuery используется хранимая процедура то ее параметры должны совпадать с полями DataSet. Для решения данной проблемы, вы можете устанавливать значения данного параметра в методе BeforeUpdateExecute например

Код: Выделить всё

procedure TForm1.MSQuery1BeforeUpdateExecute(Sender: TCustomMSDataSet;
  StatementTypes: TStatementTypes; Params: TMSParams);
begin
  Params.ParamByName('LINK_REPORTS').AsTable := MSTableData1.Table;
end;
в этом случае ошибки не возникнет, и DataSet изменит свое состояние

vso
Сообщения: 39
Зарегистрирован: Чт 24 янв 2013 11:08

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение vso » Чт 29 авг 2013 15:21

Спасибо за ответ, но не работает! :cry:

Все равно пишет ошибку - "Недопустимый тип параметра"
Вложения
Это передаваемые параметры
Это передаваемые параметры
2.jpg (220.83 КБ) 16066 просмотров
Это ошибка
Это ошибка
1.jpg (231.92 КБ) 16066 просмотров

Alexp
Devart Team
Сообщения: 349
Зарегистрирован: Пн 27 дек 2010 10:34

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение Alexp » Чт 29 авг 2013 15:48

Добрый день,

Если в Вашем примере добавить следующий метод

Код: Выделить всё

procedure TForm3.MSQuery1BeforeUpdateExecute(Sender: TCustomMSDataSet;
  StatementTypes: TStatementTypes; Params: TMSParams);
var
  i : integer;
begin
  MSTableData1.Active := true;
  for i := 0 to CheckListBox1.Count - 1 do  MSTableData1.AppendRecord([CheckListBox1.Items.Names[i],Integer(CheckListBox1.State[i])]);
  Params.ParamByName('Link_Reports').AsTable := MSTableData1.Table;
end;
а в методе BitBtn1Click оставить только вызов Post, то никаких ошибок не возникает, пожалуйста попробуйте внести описанные изменения и проверить результат

vso
Сообщения: 39
Зарегистрирован: Чт 24 янв 2013 11:08

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение vso » Пт 30 авг 2013 06:22

Добрый день!

Сделал как Вы указали, и на своем проекте и на тестовом - результат один и тот же.

И вот он в картинках:
Вложения
Та же ошибка
Та же ошибка
1.jpg (235.54 КБ) 16062 просмотра
Код как у Вас
Код как у Вас
2.jpg (229.12 КБ) 16062 просмотра

Alexp
Devart Team
Сообщения: 349
Зарегистрирован: Пн 27 дек 2010 10:34

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение Alexp » Пт 30 авг 2013 07:45

Добрый день,

Вам необходимо вместо Вашего кода, вставить в метод BeforeUpdateExecute приведенный мной код в предыдущем посте, тогда ошибки не возникнет

vso
Сообщения: 39
Зарегистрирован: Чт 24 янв 2013 11:08

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение vso » Пт 30 авг 2013 13:19

Alexp писал(а):Добрый день,

Вам необходимо вместо Вашего кода, вставить в метод BeforeUpdateExecute приведенный мной код в предыдущем посте, тогда ошибки не возникнет
Действительно я был замечен во не внимательности, но простая операция копирования Вашего кода и вставки его в тестовый проект не принесла успеха. Ошибка все таже :cry:

Alexp
Devart Team
Сообщения: 349
Зарегистрирован: Пн 27 дек 2010 10:34

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение Alexp » Пт 30 авг 2013 17:09

Добрый день,

Ниже приведен небольшой тестовый консольный пример, демонстрирующий необходимое Вам поведение, пожалуйста проверьте его работоспособность

Код: Выделить всё

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  DB,
  MSAccess,
  DBAccess,
  ActiveX;

type
  TMyClass = class
  private
    MSConnection: TMSConnection;
    MSQuery: TMSQuery;
    MSUpdateSQL: TMSUpdateSQL;
    MSStoredProc: TMSStoredProc;
    MSTableData: TMSTableData;
  public
    procedure BeforeUpdateExecute(Sender: TCustomMSDataSet;
      StatementTypes: TStatementTypes; Params: TMSParams);
    procedure test;
  end;

var
  MyClass: TMyClass;

{ MyClass }

procedure TMyClass.BeforeUpdateExecute(Sender: TCustomMSDataSet;
  StatementTypes: TStatementTypes; Params: TMSParams);
begin
    MSTableData.Open;
    MSTableData.AppendRecord(['',1]);
    Params.ParamByName('Link_Reports').AsTable := MSTableData.Table;
end;

procedure TMyClass.test;
begin
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  try
    MSConnection := TMSConnection.Create(nil);
    try
      MSConnection.Server := 'OATP';
      MSConnection.Username := 'sa';
      MSConnection.Password := 'bn1a90';
      MSConnection.Database := 'test';
      MSConnection.Connect;

      MSQuery := TMSQuery.Create(nil);
      try
        MSQuery.Connection := MSConnection;
        MSQuery.SQL.Text := 'select * from volume';
        MSQuery.BeforeUpdateExecute := BeforeUpdateExecute;
        MSQuery.Options.StrictUpdate := False;
        MSUpdateSQL := TMSUpdateSQL.Create(nil);
        try
          MSQuery.UpdateObject := MSUpdateSQL;
          MSStoredProc := TMSStoredProc.Create(nil);
          try
            MSStoredProc.Connection := MSConnection;
            MSStoredProc.StoredProcName := 'spAddVolume';
            MSUpdateSQL.InsertObject := MSStoredProc;
            MSQuery.Open;
            MSQuery.Insert;
            MSQuery.FieldByName('NUMBER').AsInteger := 1;
            MSTableData := TMSTableData.Create(nil);
            try
              MSTableData.Connection := MSConnection;
              MSTableData.TableTypeName := 'LinkReports';
              MSQuery.Post;
            finally
              MSTableData.Free;
            end;
          finally
            MSUpdateSQL.InsertObject := nil;
            MSStoredProc.Free;
          end;
        finally
          MSQuery.UpdateObject := nil;
          MSUpdateSQL.Free;
        end;
      finally
        MSQuery.Free;
      end;
    finally
      MSConnection.Free;
    end;
  finally
    CoUninitialize;
  end;
end;

begin
  MyClass := TMyClass.Create;
  try
    MyClass.test;
  finally
    MyClass.Free;
  end;
end.

vso
Сообщения: 39
Зарегистрирован: Чт 24 янв 2013 11:08

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение vso » Пн 02 сен 2013 08:23

Приложение выдает такую ошибку:
Вложения
1.jpg
1.jpg (189.6 КБ) 16045 просмотров

AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение AndreyZ » Вт 03 сен 2013 10:50

Я не могу повторить данную ошибку. Укажите пожалуйста точные версии SQL Server сервера и клиента которые Вы используете. Вы можете найти их на закладке Info редактора компонента TMSConnection.

vso
Сообщения: 39
Зарегистрирован: Чт 24 янв 2013 11:08

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение vso » Вт 03 сен 2013 11:02

Microsoft SQL Server: 10.50.4000
Microsoft SQL Server Native Client 10.0: 10.50.4000.0

AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение AndreyZ » Вт 03 сен 2013 11:33

К сожалению я по прежнему не могу повторить ошибку. Попробуйте запустить это консольное приложение из Delphi XE2 в режиме отладки и определить конкретную строчку кода которая приводит к генерации исключения.

vso
Сообщения: 39
Зарегистрирован: Чт 24 янв 2013 11:08

Re: Не одинаковое поведение Table-Valued Parameters

Сообщение vso » Вт 03 сен 2013 13:53

К сожалению я по прежнему не могу повторить ошибку. Попробуйте запустить это консольное приложение из Delphi XE2 в режиме отладки и определить конкретную строчку кода которая приводит к генерации исключения.

Код: Выделить всё

MSQuery.Post;

Закрыто