Link to home
Start Free TrialLog in
Avatar of Roger Alcindor
Roger Alcindor

asked on

How to return a DataSet from a DataSnap Server

I Have coded trivial a DataSnap server  and client with Embarcadero XE3  C++ builder which works and returns a double when a Sum() method is called.
I now wish to code the server to return a Dataset from a Table which is accessible at the server end and have the client receive the DataSet for local processing.
how do I do this ? I can't code a method at the server such as :

TDataSet  TMyClass::ATable(void)
{
      return *DataModule1->SQLTable1;
}

so I am guessing that there are DataSnap components that need to be used at the server end and the Client end ?
I attach a screen shot of the server components that I am using.

User generated image
Avatar of Roger Alcindor
Roger Alcindor

ASKER

I have found some code (shown below) for the server that would appear to provide an example of the functionality that I need.
What code would I need to receive the Dataset at the client end (Windows 32 App) ?

TDBXReader* TServerMethods1::GetCountries() {

      TDBXCommand *comm;

      try {
            DbConn->Open();
            comm = DbConn->DBXConnection->CreateCommand();
            comm->CommandType = TDBXCommandTypes_DbxSQL;
            comm->Text = "Select * from Country";

            if (!comm->IsPrepared) {
                  comm->Prepare();
            }
            return comm->ExecuteQuery();
      }
      catch (Exception* e) {
            return NULL;

      }

}
Avatar of sarabande
i don't know much about Embarcadero XE3 but, generally, you would send the data set as a byte array to the client. if the byte array is big - say greater 1k - you would send fixed sized 512 bytes packets until the data was fully sent.

at the client side you probably would wait for the data set in a separate thread what makes your program still responsive. so the general design would be

client:   connects to server
server: accepts client
client:   sends request to server
server: receives request
             checks request and returns TRUE if valid, FALSE otherwise.
client:  error on FALSE
             starts thread and passes connection handle
             returns to user interface
client
thread: waits for server response with timeout
server:  query for data set
              on success sends data of data set as a byte array to client
thread: receive dataset as byte array.
              stores bytearray into a shared dataset
              message to ui thread "data received"
              exits thread.
client:   receive message in a timer handler
              show (and/or store) data set

Sara
ASKER CERTIFIED SOLUTION
Avatar of Roger Alcindor
Roger Alcindor

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thanks for your feedback.

i looked at the solution and it looks straight-forward. however, it seems to be a sychronous call to server. if so, the foreground would "freeze" in case of a lengthy query. if that is a problem, you may consider a multi-threaded solution where you keep the user-interface working while waiting for the data set to be returned in a thread. that is not very difficult. you simply would create a new thread in the OnButtonClicked handler and would let do the thread call the server and wait for response while the OnButtonClicked would return.

Sara
I will bear that in mind for the future. In this application the query is not a lengthy one and the server is only accessed by the client when the application starts. I anticipate that the foreground freezing would not be an issue as the dataset being returned is only about 30 records.

Roger
The issue was solved on another question that I submitted and points were awarded there, see
 https://www.experts-exchange.com/questions/28670748/Can't-create-an-instance-of-a-TDBXReader-class.html?anchorAnswerId=40769868#a40769868