Клиент Datasnap выдает недопустимую порядковую ошибку

Я создал сервер Datasnap (автономный tcp/ip с помощью мастера) и добавил следующий метод сервера:

function TServerMethods1.GetSomeData(tablename : String): TDataSet;
var 
  qry: TSQLQuery;
begin
  qry := TSQLQuery.Create(nil);
  qry.SQLConnection := SQLConnection1;
  qry.SQL.Add('select *');
  qry.SQL.Add('from ' + tablename);
  qry.Open;
  Result := qry;
end;

На стороне клиента у меня есть ClientModuleUnit с цепочкой TSQLConnection->TsqlServerMethod->TDataSetProvider->TClientDataSet->DataSource->dBGrid, "подключенной" для получения данных только для чтения с сервера. Есть учебники о том, как это сделать, и я заставил его работать.

procedure TForm3.GetSomeDataClick(Sender: TObject);
begin
  if combobox1.ItemIndex > -1 then
  begin
    // ClientModule.SQLConnection1.Close;
    ClientModule.ClientDataSet1.Close;
    ClientModule.ClientDataSet1.Params.ParamValues['TableName'] := Trim(combobox1.Text);
    ClientModule.ClientDataSet1.Open;
  end;
end;

В combobox1 есть несколько имен таблиц. При первом выборе таблицы данные извлекаются и заполняют DBGrid. Если затем я выберу таблицу с меньшим количеством полей, чем первая таблица, я получу исключение Invalid Ordinal. Интересно, что если я сначала выбираю таблицу с меньшим количеством полей, то второй вызов использует поля из первого вызова, и не все поля отображаются.

Ошибка возникает в Data.DBXCommon.TDBXValueList.GetValueType - на самом деле слишком глубокая и сложная для меня, чтобы понять.

Конечно, если я закрою и открою соединение Datasnap (прокомментировано выше), то сообщение invalid ordinal не появится, и оно будет работать так, как я ожидаю.

Является ли это ошибкой или просто ограничением текущей реализации Datasnap (DBX)?


person nolaspeaker    schedule 13.08.2018    source источник
comment
Я не создаю никаких постоянных (T) полей или TFieldDefs ни на сервере, ни на клиенте. Здесь все динамическое творение.   -  person nolaspeaker    schedule 13.08.2018


Ответы (1)


Такое поведение подразумевает, что ваши поля остаются между вызовами. Поэтому я бы очистил поля в этих наборах данных (sqlServerMethod1 и Clientdataset1), прежде чем загружать их новыми данными.

procedure TForm3.GetSomeDataClick(Sender: TObject);
begin
  if combobox1.ItemIndex > -1 then
  begin
    ClientModule.ClientDataSet1.Close;

    ClientModule.ClientDataSet1.FieldDefs.Clear;
    ClientModule.sqlServerMethod.FieldDefs.Clear;

    ClientModule.ClientDataSet1.Params.ParamValues['TableName'] := Trim(combobox1.Text);
    ClientModule.ClientDataSet1.Open;
  end;
end;
person Marc Guillot    schedule 13.08.2018
comment
Это отличный ответ. Меня беспокоила эта проблема, и я долгое время прибегал к обходному пути закрытия соединения. - person nolaspeaker; 13.08.2018