Upload DataTable to server from Delphi to .NET

I am trying to stream a delphi TDAMemDataTable to a .NET System.Data.DataTable but get an error when deserializing.

I currently get exception RemObjects.DataAbstract.DAException: ‘Unexpected end of stream’
Note: The binary data gets passed through an intermediate RO client/server but I assume this should not matter.

Should this work? What is wrong with the code?

My delphi client code:
function UploadCloudData(DataTable:TDAMemDataTable): Boolean;
var
tabledata:Binary;
streamer:TDABin2DataStreamer;
begin
tabledata:=nil;
try
streamer:=TDABin2DataStreamer.Create(nil);
try
tabledata:=Binary.Create();
streamer.WriteDataset(tabledata,DataTable,[woSchema,woRows],-1);
finally
streamer.Finalize();
FreeAndNil(streamer);
end;
Result:=(Service as IPharmacyCloudService).UploadCloudData(tabledata);
end;

My .NET server code:
var streamer = new RemObjects.DataAbstract.Bin2DataStreamer();
var stream = new System.IO.MemoryStream(tabledata.ToArray());
var dataTable = new System.Data.DataTable(tablename);
//var schema = streamer.ReadDataTableSchema(queryinfo.tablename);
streamer.ReadDataTable(stream, tablename, dataTable, true, true);

I am using build 1521 (both delphi and .NET)

Hi,

I can recommend to use “full version” of code like

      lStreamer.Initialize(aStream, aiWrite);
      try
        lStreamer.WriteDataset(table, [woRows, woSchema]);
      finally
        lStreamer.Finalize;
      end;

because calling Finalize w/o Initialize can break stream.

another hint: try to set position of tabledata to 0 before uploading to .net server.

I cannot call Initialize since this is already part of the WriteDataset function in uDADataStreamer
(an exception is thrown)

function TDADataStreamer.WriteDataset(Stream: TStream;
const Source: IDADataset; Options: TDAWriteOptions;
MaxRows: integer): integer;
begin
Initialize(Stream, aiWrite);
try
result := WriteDataset(Source, Options, MaxRows);
finally
Finalize;
end;
end;

I have removed my extra Finalize and this seems to solve the issue.
Thanks for the help

Hi,

we have several overloads:

    function WriteDataset(const Source: IDADataset;
      Options: TDAWriteOptions;
      MaxRows: integer;
      ADynFieldNames: array of string): integer; overload;

    function WriteDataset(const Source: IDADataset;
      Options: TDAWriteOptions;
      MaxRows: integer = AllRows): integer; overload;

    function WriteDataset(Stream: TStream;
      const Source: IDADataset;
      Options: TDAWriteOptions;
      MaxRows: integer = AllRows): integer; overload;

1st and 2nd methods requires Initialize, 3rd - doesn’t

Thanks for the info.
Meanwhile I have added WriteDelta which looks OK but I do not succeed in enabling ReducedDelta.
Regardless of the streamer SendReducedDelta parameter the Delta.FieldsFilter appears to contain all fields instead of only the modified ones.
How can I enable reduced delta for a TDAMemDataTable?
The HasReducedDelta property is readonly contrary to what the documentation shows.

Note: I test by performing an insert + apply and then a modification of a single field. I evaluate the delta before the next apply.

Hi,

Reduced delta means that non-changed fields have NULL value instead of real values.
Delta in any case will contain all fields.

Thanks,
What is the best way then to identify the modified fields?
How do we distinguish setting the value to NULL and not changing the value?

Hi,

we use this check:

if ReducedDeltaMode and
   ROVariantsEqual(aChange.OldValueByName[fieldname],
                   aChange.NewValueByName[fieldname]) then Continue; // doesn't modified