I created a Datasnap server (stand-alone tcp/ip using the Wizard) and added the following server method:
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;
On the client side, I have a ClientModuleUnit
with a TSQLConnection->TsqlServerMethod->TDataSetProvider->TClientDataSet->DataSource->dBGrid
chain "wired up" to retrieve the readonly data from the server. There are tutorials about how to do this, and I have made it work.
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;
There are several tablenames in the combobox1. The first time I select a table, the data is retrieved and populates the DBGrid. If I then choose a table that has less fields than the first table, I get an Invalid Ordinal exception. Interestingly, if I choose a table that has less fields first, then the second call uses the fields from the first call - and not all fields are displayed.
The error is raised in Data.DBXCommon.TDBXValueList.GetValueType
- too deep and complicated for me to understand, really.
Of course, if I close and open the Datasnap connection (commented above), then the invalid ordinal
message isn't raised and it works as I expect it should.
Is this a bug, or just a limitation of the current Datasnap (DBX) implementation?
This behavior implies that your fields remain between calls. So I would clear the fields on those datasets (sqlServerMethod1 & Clientdataset1) before loading them with new data.
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;