Show/Hide Toolbars

TMS XData Documentation

In addition to TXDataWebClient, you have the option to use TXDataWebDataset to communicate with TMS XData servers from web applications. It's even higher level of abstraction, at client side you will mostly work with the dataset as you are used to in traditional Delphi applications, and XData Web Client framework will translate it into REST/JSON requests.

 

Setting it up is simple:

 

1. Associate a TXDataWebConnection to the dataset through the Connection property (you can do it at design-time as well). Note that the TXDataWebConnection must be previously connected. Performing operations with TXDataWebDataset won't automatically setup the connection.

 

XDataWebDataset1.Connection := XDataWebConnection1;

 

2. Set the value for EntitySetName property, with the name of the entity set in XData server you want to manipulate data from. You can also set this at design-time, and object inspector will automatically give you a list of available entity set names.

 

XDataWebDataset1.EntitySetName := 'artist';

 

3. Optionally: specify the persistent fields at design-time. As with any dataset, you can simply use the dataset fields editor and add the desired fields. TXDataWebDataset will automatically retrieve the available fields from XData server metadata. If you don't, as with any dataset in Delphi, the default fields will be created.

 

And your dataset is set up. You can the use it in several ways, as explained below.

 

Loading data automatically

 

Once the dataset is configured, you just need to call Load method to retrieve data:

 

XDataWebDataset1.Load;

 

This will perform a GET request in XData server to retrieve the list of entities from the specific entity set. Always remember that such requests are asynchronous, and that's why you use Load method instead of Open. Load will actually perform the request, and when it's finished, it will provide data to the dataset and only then, call Open method. Which in turn will fire AfterOpen event. If you want to know when the request is finished and data is available in the dataset, use the AfterOpen event.

 

To filter out results, you can (and should) use the QueryString property, where you can put any query option you need, including $filter and $top, which you should be use to filter out the results server-side and avoiding retrieving all the objects to the client. Minimize the number of data sent from the server to the client!

 

XDataWebDataset1.QueryString := '$filter=startswith(Name, ''John'')&$top=50';
XDataWebDataSet1.Load;

 

Paging results

 

The above example uses a raw query string that includes "&$top=50" to retrieve only 50 records. You can do paging that way, by building the query string accordingly. But TXDataWebDataset provides additional high-level properties for paging results in an easier way. Simply use QueryTop and QuerySkip property to define the page size and how many records to skip, respectively:

 

XDataWebDataset1.QueryTop := 50// page size of 50
XDataWebDataset1.QuerySkip := 100// skip first 2 pages
XDataWebDataset1.QueryString := '$filter=startswith(Name, ''John'')';
XDataWebDataSet1.Load;

 

The datase also provides a property ServerRecordCount which might contain the total number of records in server, regardless of page size. By default, this information is not retrieved by the dataset, since it requires more processing at server side. To enable it, set ServerRecordCountMode:

 

XDataWebDataset1.ServerRecordCountMode := smInlineCount;

 

When data is loaded from the dataset (for example in the AfterOpen event), you can read ServerRecordCount property:

 

procedure TForm4.XDataWebDataSet1AfterOpen(DataSet: TDataSet);
begin
  TotalRecords := XDataWebDataset1.ServerRecordCount;
end;

 

Loading data manually

 

Alternatively you can simply retrieve data from the server "manually" using TXDataWebClient (or even using raw HTTP requests, if you are bold enough) and provide the retrieved data to the dataset using SetJsonData. Since the asynchronous request was already handled by you, in this case where data is already available, and you can simply call Open after setting data:

 

procedure TForm1.LoadWithXDataClient;
 
  procedure OnSuccess(Response: TXDataClientResponse);
  begin
    XDataWebDataset1.SetJsonData(Response.Result);
    XDataWebDataset1.Open;
  end;
 
begin
  XDataWebClient1.List('artist''$filter=startswith(Name, ''New'')', @OnSuccess);
end;

 

Modifying data

 

When using regular dataset operations to modify records (Insert, Append, Edit, Delete, Post), data will only be modified in memory, client-side. The underlying data (the object associated with the current row) will have its properties modified, or the object will be removed from the list, or a new object will be created. You can then use those modified objects as you want - manually send changes to the server, for example.

 

But TXDataWebDataset you can have the modifications to be automatically and transparently sent to the server. You just need to call ApplyUpdates:

 

XDataWebDataset1.ApplyUpdates;

 

This will take all the cached modifications (all objects modified, deleted, inserted) and will perform the proper requests to the XData server entity set to apply the client modifications in the server.

 

Other properties

 

Name

Description

property SubPropsDepth: Integer

Allows automatic loading of subproperty fields. When adding persitent fields at design-time or when opening the dataset without persistent fields, one TField for each subproperty will be created. By increasing SubpropsDepth to 1 or more, dataset will also automatically include subproperty fields for each property in each association, up to the level indicated by SubpropsDepth. For example, if SubpropsDepth is 1, and the entity type has an association field named "Customer", the dataset will also create fields like "Customer.Name", "Customer.Birthday", etc.. Default is 0 (zero).

property CurrentData: JSValue

Provides the current value associated with the current row. Even though CurrentData is of type JSValue for forward compatibility, for now CurrentData will always be a TJSObject (an object).