Страница 1 из 2

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

Добавлено: Пн 26 авг 2013 07:41
vso
Добрый день!

Есть связь 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.

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

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

Добавлено: Вт 27 авг 2013 08:28
vso
Попробовал перенести вызов процедуры в 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

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

Добавлено: Вт 27 авг 2013 11:31
Alexp
Добрый день,

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

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

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

Добавлено: Чт 29 авг 2013 12:19
Alexp
Добрый день,

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

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

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

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

Добавлено: Чт 29 авг 2013 15:21
vso
Спасибо за ответ, но не работает! :cry:

Все равно пишет ошибку - "Недопустимый тип параметра"

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

Добавлено: Чт 29 авг 2013 15:48
Alexp
Добрый день,

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

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

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, то никаких ошибок не возникает, пожалуйста попробуйте внести описанные изменения и проверить результат

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

Добавлено: Пт 30 авг 2013 06:22
vso
Добрый день!

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

И вот он в картинках:

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

Добавлено: Пт 30 авг 2013 07:45
Alexp
Добрый день,

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

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

Добавлено: Пт 30 авг 2013 13:19
vso
Alexp писал(а):Добрый день,

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

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

Добавлено: Пт 30 авг 2013 17:09
Alexp
Добрый день,

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

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

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.

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

Добавлено: Пн 02 сен 2013 08:23
vso
Приложение выдает такую ошибку:

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

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

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

Добавлено: Вт 03 сен 2013 11:02
vso
Microsoft SQL Server: 10.50.4000
Microsoft SQL Server Native Client 10.0: 10.50.4000.0

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

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

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

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

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

MSQuery.Post;