How to make an async request to Relativity Server from Delphi?

I am using a Relativity Server connected to an MSSQL database to expose tables, views, and commands.
One of the views takes time to return the results, and I want to use an asynchronous request.
I used RemoteDataAdapter.BeginFill to make the request, and I receive the callback when it is done.
How can I update the TDAMemDataTable, the data source for a DevExpress TcxGrid? Should I keep it disconnected until I receive the data?
Is there any way to log or monitor the commands going to Relativity Server to minimize the traffic?

Hi,

you should just call RDA.EndFill in callback;

Note: you should close table before BeginFill otherwise data will be appended :

.

I can suggest to use DA SQL . You can use sql like

select top x skip y fld1, fld2 from table

in case you have a lot of rows.
in callback method, you can ask for the rest so
1st sql can be like select top 20 fld1, fld2 from table,
2nd one is select top 20 skip 20 fld1, fld2 from table, etc

My original code was:

        tbl_ViewAllCrashes.Params.ParamByName('CrashID').Value := ACrashID;
        tbl_ViewAllCrashes.Open;
        if Assigned(AOnFormInit) then
            AOnFormInit;

The new code is:

            RemoteDataAdapter.BeginFill
            (
                procedure (const aRequest: IROAsyncRequest)
                begin
                    if aRequest.Done then
                        begin
                            RemoteDataAdapter.EndFill(aRequest); //Access Violation

                            inherited Open(AOnFormInit)
                        end
                    else
                        LogError('ViewAllCrashes.Open', 'AsyncRequest failed');
                end,
                @tbl_ViewAllCrashes,
                [tbl_ViewAllCrashes],
                nil
            );

I get an access violation at EndFill().
I was using DASQL but removed it by adding a parameter to the Relativity table.
I can use it again for loading the data on smaller chunks.
But this first test fails.

Hi,

I can’t reproduce AV at EndFill.
my code is

  ClientDataModule.RemoteDataAdapter.BeginFill(
      procedure (const aRequest: IROAsyncRequest)
      begin
        if aRequest.Done then
          ClientDataModule.RemoteDataAdapter.EndFill(aRequest);
      end,
      @ClientDataModule.tbl_Clients,
      [ClientDataModule.tbl_Clients]
      );

testcase.zip (91.2 KB)

Sorry, I forgot to mention that the table I’m reading has several smaller tables as details, so that they are also opened when the master table is opened.
The access violation happens reading from the server, probably because of some multithreading issue.

Hi,

in general, it is possible to use code w/o callback like

  ClientDataModule.RemoteDataAdapter.BeginFill(
      nil,
      nil,
      [ClientDataModule.tbl_Clients]
      );

in this case, default callback (TDAGetDataRequestAsync.DefaultCallback) is used.

I tried your solution, that is, not using a callback, and it runs (but I need a callback to know when to update a few things on the grid).
The simplest call to EndFill fails.

        RemoteDataAdapter.BeginFill
        (
            procedure (const aRequest: IROAsyncRequest)
            begin
                if aRequest.Done then
                        RemoteDataAdapter.EndFill(aRequest);
            end,
            nil,
            [
                tbl_ViewAllCrashes
                ,tbl_priorities
                ,tbl_crash_threads
                ,tbl_thread_stacktraces
                ,tbl_crash_modules
                ,tbl_crash_processes
                ,tbl_crash_hardware
                ,tbl_crash_cpu_registers
                ,tbl_crash_stack_dumps
                ,tbl_crash_disassembling
            ],
            nil
        );

Hi,

I need your testcase that reproduces this case.

it works w/o any issues on my side:

  ClientDataModule.RemoteDataAdapter.BeginFill(
      procedure (const aRequest: IROAsyncRequest)
      begin
        if aRequest.Done then
          ClientDataModule.RemoteDataAdapter.EndFill(aRequest);
      end,
      nil,
      [
        ClientDataModule.tbl_Clients,
        ClientDataModule.tbl_History,
        ClientDataModule.tbl_IncomePricesReport,
        ClientDataModule.tbl_OrderDetails,
        ClientDataModule.tbl_Orders,
        ClientDataModule.tbl_OrderStatus,
        ClientDataModule.tbl_OrderType,
        ClientDataModule.tbl_PriceList,
        ClientDataModule.tbl_ProductGroups,
        ClientDataModule.tbl_Products,
        ClientDataModule.tbl_Providers,
        ClientDataModule.tbl_RestReport,
        ClientDataModule.tbl_SalesReport,
        ClientDataModule.tbl_Users,
        ClientDataModule.tbl_Vendors,
        ClientDataModule.tbl_Workers]
      );

The only difference I see is that my DevExpress data-aware components start disconnected from their data sources, so that I only need to populate the main table and it will trigger the Active property of the detail tables.
I need to know when the data was loaded to connect the components and get some data.
My middle tier is Relativity Server.
The error I’m receiving is related to some streaming (RO SDK getting some information from Relativity) and what worries me is that it is an access violation with the standard callback.
The same code executes correctly without the callback.
As I’m using a data module per form, and this is the only one I tried to open, there is no more traffic against the server.

Hi,

Can you debug this code and check that RemoteDataAdapter isn’t nil, pls?

AV can be raised if you have <nil>.EndFill(aRequest) case.

image
Debugging the code.


I will check if there is a background task using the same data module.

Hi,

Can you show callstack, pls?

image
This is after stopping everything else and receiving the A/V.
image
The execution starts here:
image

I commented out the anonymous procedure and used nil as before, but this time, after reading everything in 4 chunks, I received the same error (and this time there is nothing else making requests to Relativity).
image
Events:

Hi,

is it possible to do simple testcase that reproduces this issue with standard DASamples domain?

I will try it later. Right now, I’m improve performance by loading the master table after severing the relationships of all the detail tables and restoring the relationships after loading the master. In that way, when the detail tables get loaded, they will bring only the rows for the selected master record.
I wanted to do it at once, like in client/server mode, but it was taking too long.

Hi,

You can specify how to details tables will be loaded via table.MasterOptions and table.DetailOptions properties.

default values of these properties are

[moCascadeOpenClose, moCascadeApplyUpdates, moCascadeDelete]

and

[dtCascadeOpenClose,  dtCascadeApplyUpdates,  
 dtAutoFetch, dtDisableLogOfCascadeDeletes, 
 dtIncludeInAllInOneFetch, dtDisableFetchForClonedTables];
1 Like