RTC Forums
April 29, 2024, 02:29:53 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: 1 [2]
  Print  
Author Topic: Blob  (Read 9064 times)
HelgeLange
RTC Expired
*
Posts: 100


« Reply #15 on: September 11, 2017, 05:56:58 PM »

Sorry if I get into the discussion, I use UniDAC (same as the OP) all the time with RTC and I send blobs another way.
I load a UniQuery as TVirtualTable (comes with UniDAC and also is a free component) and I save the TVirtualTable as one bytestream in RTC, it contains all rows selected by the original query with as many blobs as you like.
When the function is called and executed on the server side I take the bytestream and load it into a VirtualTable there. From there you an use a batchmove to insert it into your server database or whatever.

I place the code AS IT IS here and you can extrapolate what you need :

Client side:

Code:

// here I only send a DataId, which will  be returned and where I can identify which data was asked for
// then a SQL query, that way I can execute whatever I want
// also which database I want to query (my server can handle multiple DBs)
// LU is a datetime for LastUpdate so I can filter only data that was changed since the last time I checked
procedure TRtcClient.DoSyncronizeFromServer(DataId: Integer);
var FI : TRtcFunctionInfo;
    LU : TDateTime;
begin
  FI := cmMobile.Prepare('MobileSyncServerTables');
  FI.asInteger[RTC_PARAM_DATA_ID] := DataId;
  FI.asString[RTC_PARAM_SQL_TEXT] := __Internal_GetSQL(DataId, LU);
  FI.asString[RTC_PARAM_FIELD_DATABASE] := RemoteDataBase;
  FI.asDateTime[RTC_PARAM_LAST_UPDATE] := LU;
  cmMobile.Call(Result_SyncServerTable);
end;

// the object VT is from type TVirtualTable
// so when i get a rtc_Record and it has data (_Result.asBoolean[RTC_PARAM_HAS_DATA]) then I load the ByteStream into the VirtualTable
// and call __Internal_ReceiveSyncData which processes these data
// and afterwards I call all the listener to tell them that something has changed
procedure TRtcClient.Result_SyncServerTableReturn(Sender: TRtcConnection; Data, Result: TRtcValue);
var _Result : TRtcRecord;
    DataId : Integer;
    aStream : TMemoryStream;
begin
  If Result.isType = rtc_Record Then begin
    _Result := Result.asRecord;
    If _Result.asBoolean[RTC_PARAM_HAS_DATA] Then begin
      VT.Open;
      aStream := TMemoryStream(_Result.asByteStream[RTC_PARAM_VTDATA]);
      aStream.Position := 0;
      VT.LoadFromStream(aStream);
      DataId := _Result.asInteger[RTC_PARAM_DATA_ID];
//      VT.SaveToFile('F:\ServerData_' + DataId.ToString + '.vdb');
      __Internal_ReceiveSyncData(DataId, VT, _Result.asDateTime[RTC_PARAM_LAST_UPDATE]);
      VT.Close;
      CallListener(DataId);
    end;
  end;
end;



Serverside :

Code:
procedure TDMBRS.fctSyncServerTableExecute(Sender: TRtcConnection; Param: TRtcFunctionInfo; Result: TRtcValue);
var _Result : TRtcRecord;
    bStream : TStream;
begin
  {$IFDEF USE_CODESITE}CodeSite.TraceMethod( Self, Self.ClassName + '.fctSyncServerTableExecute' );{$ENDIF}
  ConnectionTimer.Enabled := False;
  FdtLastUsed := Now;
  _Result := Result.NewRecord;
  _Result.asDateTime['LU'] := Now;   // define this as the last check point
  {$IFDEF USE_CODESITE} CodeSite.Send(csmLevel4, 'LastUpdate', FormatDateTime(FormatSettings.ShortDateFormat, Param.asDateTime['LU']) + ' ' + FormatDateTime(FormatSettings.ShortTimeFormat, Param.asDateTime['LU'])); {$ENDIF}
  _Result.asBoolean['HasData'] := False;
  {$IFDEF USE_CODESITE} CodeSite.Send(csmLevel4, 'SQL', Param.asString['SQL']); {$ENDIF}
  If Not DBConnection.Connected Then
    DBConnection.Connected := True;
  If Not ReadTransaction.Active Then
    ReadTransaction.StartTransaction;
  QR.SQL.Text := Param.asString['SQL'];
  QR.ParamByName('LU').AsDateTime := Param.asDateTime['LU'];
  try
    QR.Open;
  except
    on E: Exception do begin
      {$IFDEF USE_CODESITE} CodeSite.Send(csmLevel1, 'Error', E.Message); {$ENDIF}
      ConnectionTimer.Enabled := True;
      raise Exception.Create(Self.ClassName + '.fctSyncServerTableExecute ERROR: ' + #13#10 + E.Message);
    end;
  end;
  {$IFDEF USE_CODESITE} CodeSite.Send(csmLevel4, 'RecordCount', QR.RecordCount); {$ENDIF}
  If QR.RecordCount > 0 Then begin
    bStream := _Result.NewByteStream('vtData');
    if VT.Active then
      VT.Close;
    VT.Open;
    VT.Assign(QR);
    VT.SaveToStream(bStream, True, True);
    VT.Close;
    _Result.asBoolean['HasData'] := True;
    _Result.asInteger['DataId'] := Param.asInteger['DataId'];
  end;
  QR.Close;
  ConnectionTimer.Enabled := True;
end;


on serverside the interesting part start in the Try...Except block with the query itself, it's a simple TUniQuery. I send the query from the client to be executed.
If there are date (If QR.RecordCount > 0 Then) Then I create a new ByteStream, I load the query into the VirtualTable and the VT saves it to the ByteStream


The same way it works when you upload to the server, just make the query, VirtualTable.Assign also copies the content of any blob and send the stream Smiley


I hope that helps
Logged
cdhaene
RTC Expired
*
Posts: 13


« Reply #16 on: September 11, 2017, 08:50:17 PM »

Thanks! I'll give it a try right away
Logged
Pages: 1 [2]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.023 seconds with 16 queries.