The purpose of the
DelphiDataSetToRtc function is to create a
TRtcDataSet object by using field definition and row data stored in a
TDataSet object. First, it uses the
SetFields method to create fields (one field at a time) and then it loops from First to Last row of a TDataSet and copies data field-by-field. Here is the complete function code, as implemented in the "rtcDB.pas" unit ...
procedure DelphiDataSetToRtc(DelphiDS:TDataSet; rtcDS:TRtcDataSet; ClearFieldDefs:boolean=True; OnlyDataFields:boolean=True);
var
flds:integer;
fldname:RtcWideString;
field:TField;
fstream:TStream;
begin
if ClearFieldDefs then
begin
rtcDS.Clear;
for flds:=0 to DelphiDS.Fields.Count-1 do
begin
field:=DelphiDS.Fields[flds];
if assigned(field) then
begin
fldname:=RtcWideString(field.FieldName);
if (OnlyDataFields=False) or (field.FieldKind=fkData) then
rtcDS.SetField(fldname,
RTC_DB2FIELD_TYPE(field.DataType),
field.Size,
field.Required);
end;
end;
end;
DelphiDS.First;
while not DelphiDS.Eof do
begin
rtcDS.Append;
for flds:=0 to rtcDS.FieldCount-1 do
begin
fldname:=rtcDS.FieldName[flds];
field:=DelphiDS.FindField(String(fldname));
if assigned(field) then
if not field.IsNull then
if (OnlyDataFields=False) or (field.FieldKind=fkData) then
if field.isBlob then
begin
fstream:=DelphiDS.CreateBlobStream(field,bmRead);
try
if {$IFNDEF FPC} TBlobField(field).GraphicHeader and {$ENDIF}
( (field.DataType = ftGraphic) or
(field.DataType = ftTypedBinary) ) then
RtcSkipGraphicFieldHeader(fstream);
rtcDS.NewByteStream(fldname).CopyFrom(fstream,fstream.Size-fstream.Position);
finally
fstream.Free;
end;
end
else
case RTC_FIELD2VALUE_TYPES[rtcDS.FieldType[fldname]] of
rtc_Currency: rtcDS.asCurrency[fldname]:=field.AsCurrency;
rtc_DateTime: rtcDS.asDateTime[fldname]:=field.AsDateTime;
rtc_String: rtcDS.asString[fldname]:=RtcString(field.AsString);
{$IFDEF UNICODE}rtc_Text: rtcDS.asText[fldname]:=field.AsWideString;{$ENDIF}
else rtcDS.Value[fldname]:=field.Value;
end;
end;
DelphiDS.Next;
end;
end;
The function above uses
RTC_FIELD2VALUE_TYPES to handle standard field types, but since you want to handle a custom field type, you should directly check the field type on the
field:TField object (provided by the TDataSet class in Delphi), then extract raw data from that field. The actual code you will need to write to extract the data will depend on the field type, Database and Database Access components you are using.
I'm NOT going to try and explain how to extract data from a Database, because that has nothing to do with the RTC SDK, but with the Database and Database Access components you are using. I would suggest, however, that you find a way to get your field data into a TStream, so you can store it
asByteStream (similar to the code used above for storing BLOB fields), or ... into an array of bytes, so you can directly assign it to the
asByteArray property, or ... as plain String, in which case you can assign it directly to the
asText property (to avoid Unicode problems, in case Unicode characters are used). When writing your function for the Server, keep in mind that you will also need to extract that data on the Client.
NOTE: TRtcClientDataSet and TRtcDataSetMonitor components only support flat table structures and do NOT support extracting changes from nested tables (tables inside tables). In other words, if a field in your Database contains an entire Table, you will NOT be able to use the TRtcClientDataSet or the TRtcDataSetMonitor component to extract changes to rows or fields on the inner table.
Best Regards,
Danijel Tkalcec