Instantiating an OData Model (2024)

The OData Model enables binding of controls to data from OData services.

The OData model is a server-side model, meaning that the data set is onlyavailable on the server and the client only knows the currentlyvisible (requested) data. Operations, such as sorting and filtering,are done on the server. The client sends a request to the server andshows the returned data.

Note

Requests to the back end are triggered by list bindings(ODataListBinding), element bindings(ODataContextBinding), and CRUD functionsprovided by the ODataModel. Property bindings(ODataPropertyBindings) do not triggerrequests.

The OData model currently supports OData version 2.0.

The following two versions of the OData model are implemented:sap.ui.model.odata.ODataModel andsap.ui.model.odata.v2.ODataModel. Thev2.ODataModel has an improved feature set and new features willonly be implemented in this model. sap.ui.model.odata.ODataModel isdeprecated. We recommend to only use v2.ODataModel.

The following table shows the supported features for both OData models:

Feature

sap.ui.model.odata.v2.ODataModel

sap.ui.model.odata.ODataModel

OData version support

2.0

2.0

JSON format

Yes (default)

Yes

XML format

Yes

Yes (default)

Support of two-way binding mode

Yes; for property changes only, not yet implemented for aggregations

Experimental; only properties of one entity can be changed at the same time

Default binding mode

One-way binding

One-way binding

Client-side sorting and filtering

Yes; see sap.ui.model.odata.OperationMode in the APIreference

No

$batch

Yes; all requests can be batched

Only manual batch requests are possible

Data cache in model

All data is cached in the model

Manually requested data is not cached

Automatic refresh

Yes (default)

Yes

Message handling

Yes, see Managing UI and Server Messages

No

Note

Be aware of the Same-Origin-Policy security concept which prevents accessto back ends on different domains or sites.

The requests to the service to fetch data are made automatically based on the databindings that are defined for the controls.

Creating the Model Instance

One OData model instance can only cover one OData service. For accessingmultiple services, you have to create multiple OData modelinstances. The only mandatory parameter when creating anODataModel instance is the service URL. Itcan be passed as first parameter or within themParameters map to the constructor.

var oModel = new sap.ui.model.odata.v2.ODataModel("http://services.odata.org/Northwind/Northwind.svc/");var oModel = new sap.ui.model.odata.v2.ODataModel({serviceUrl: "http://services.odata.org/Northwind/Northwind.svc"});

When creating an ODataModel instance, a request is sentto retrieve the service metadata:

http://services.odata.org/Northwind/Northwind.svc/$metadata

Service Metadata

The service metadata is cached per service URL. Multiple OData models that are using the sameservice can share this metadata. Only the first model instance triggers a$metadata request. A JSON representation of the servicemetadata can be accessed by calling the getServiceMetadata() methodon an Odata model instance.

var oMetadata = oModel.getServiceMetadata();

Note

In the v2.ODataModel, the service metadata is loadedasynchronously. It is not possible to load it synchronously. To get notifiedwhen the loading is finished, attach the metadataLoadedevent.

Adding Additional URL Parameters

For OData services, you can use URL parameters for configuration. SAPUI5 sets most URLparameters automatically, according to the respective binding.

For authentication tokens or general configuration options, for example,you can add additional arguments to the request URL. Some of theparameters must not be included in every request, but shouldonly be added to specific aggregation or element bindings, suchas $expand or $select. Forthis, the binding methods provide the option to pass a map ofparameters, which are then included in all requests for thisspecific binding. The OData model currently only supports$expand and $select.

There are different ways to add URL parameters to the requests:

  • Appending parameters to the service URL:

    var oModel = new sap.ui.model.odata.v2.ODataModel("http://myserver/MyService.svc/?myParam=value&myParam2=value");

    These parameters will be included in every request sent to the ODataserver.

  • Passing URL parameters with the mparameters map

    You can pass URL parameters that are used for $metadatarequests only (metadataUrlParams) as well as URL parametersthat are included only in data requests (serviceUrlParams).The parameters are passed as maps:

    var oModel = new sap.ui.model.odata.v2.ODataModel({ serviceUrl: "http://services.odata.org/Northwind/Northwind.svc", serviceUrlParams: { myParam: "value1", myParam2: "value2" }, metadataUrlParams: { myParam: "value1", myParam2: "value2" }});

Custom HTTP Headers

You can add custom headers which are sent with each request. To do this, provide a map ofheaders to the OData model constructor or use the setHeaders()function:

Addressing Entities: Binding Path Sytnax

The binding path syntax for OData models matches the URL path relative to the serviceURL used in OData to access specific entities or entity sets.

You access the data provided by the OData model according to the structure of the ODataservice as defined in the metadata of a service. URL parameters, such as filters,cannot be added to a binding path. A binding path can be absolute or relative.Absolute binding paths are resolved immediately. A relative path can only beresolved if it can be automatically converted into an absolute binding path. If, forexample, a property is bound to a relative path and the parent control is then boundto an absolute path, the relative property path can e resolved to an absolutepath.

The following binding samples within the ODataModel aretaken from the Northwind demo service.

Absolute binding path (starting with a slash ('/')):

"/Customers""/Customers('ALFKI')/Address"

Relative binding paths that can be resolved with a context (for example"/Customer('ALFKI')"):

"CompanyName""Address""Orders"

Resolved to:

"/Customer('ALFKI')/CompanyName""/Customer('ALFKI')/Address""/Customer('ALFKI')/Orders"

Navigation properties, used to identify a single entity or a collection ofentities:

"/Customers('ALFKI')/Orders""/Products(1)/Supplier"

For more information on addressing OData entries, see the URI conventions documentation onhttp://www.odata.org.

Accessing Data from an OData Model

The data requested from an OData service is cached in the OData model. It can be accessed bythe getData() and the getProperty() method, whichreturns the entity object or value. These methods do not request data from thebackend, so you can only access already requested and cached entities:

oModel.getData("/Customer('ALFKI')");oModel.getProperty("/Customer('ALFKI')/Address");

You can only access single entities and properties with these methods. To access entity sets,you can get the binding contexts of all read entities via a list binding. The valuesreturned by these methods are copies of the data in the model, not references as inthe JSONModel.

Caution

Do not modify objects or values inside the model manually;always use the provided API to change data in the model, or use two-way binding(see Two-way Binding section below).

Creating Entities

To create entities for a specified entity set, call thecreateEntry() method. The method returns a context object thatpoints to the newly created entity. The application can bind against these objectsand change the data by means of two-way binding. To store the entities in the ODatabackend, the application calls submitChanges(). To reset thechanges, the application can call the deleteCreatedEntry()method.

The application can choose the properties that shall be included in the createdobject and can pass its own default values for these properties. Per default, allproperty values are be empty, that is, undefined.

Note

The entity set and the passed properties must exist in the metadata definition ofthe OData service.

// create an entry of the Products collection with the specified properties and valuesvar oContext = oModel.createEntry("/Products", { properties: { ID:99, Name:"Product", Description:"new Product", ReleaseDate:new Date(), Price:"10.1", Rating:1} });// binding against this entityoForm.setBindingContext(oContext);// submit the changes (creates entity at the backend)oModel.submitChanges({success: mySuccessHandler, error: myErrorHandler});// delete the created entityoModel.deleteCreatedEntry(oContext);

If created entities are submitted, the context is updated with the path returnedfrom the creation request and the new data is imported into the model. So thecontext is still valid and points to the new created entity.

CRUD Operations

The OData model allows manual CRUD (create, read, update, delete) operations on the ODataservice. If a manual operation returns data, the data is imported into the datacache of the OData model. All operations require a mandatory sPathparameter as well as an optional mParameters map. Thecreate and update methods also require amandatory oData parameter for passing the created or changed dataobject. Each operation returns an object containing a function abort, which can beused to abort the request. If the request is aborted, the error handler is called.This ensures that the success or the error handler is executed for every request. Itis also possible to pass additional header data, URL parameters, or an eTag.

  • Creating entities

    The create function triggers a POST request to an ODataservice which was specified at creation of the OData model. The applicationhas to specify the entity set, in which the new entity and the entity datais to be created.

    var oData = { ProductId: 999, ProductName: "myProduct"}oModel.create("/Products", oData, {success: mySuccessHandler, error: myErrorHandler});
  • Reading entities

    The read function triggeres a GET request to a specifiedpath. The path is retrieved from the OData service which was specified atcreation of the OData model. The retrieved data is returned in thesuccess callback handler function.

    oModel.read("/Products(999)", {success: mySuccessHandler, error: myErrorHandler});
  • Updating entities

    The update function triggers a PUT/MERGErequest to an OData service which was specified at creation of the ODatamodel. After a successful request to update the bindings in the model, therefresh is triggered automatically.

    var oData = { ProductId: 999, ProductName: "myProductUpdated"}oModel.update("/Products(999)", oData, {success: mySuccessHandler, error: myErrorHandler});
  • Deleting entities

    The remove function triggers a DELETE request to an ODataservice which was specified at creation of the OData model. The applicationhas to specify the path to the entry which should be deleted.

    oModel.remove("/Products(999)", {success: mySuccessHandler, error: myErrorHandler});
  • Refresh after change

    The model provides a mechanism to automatically refresh bindings that depend on changed entities. If you carry out a create,update or remove function, the model identifies the bindings and triggers a refresh forthese bindings. If the model runs in batch mode, the refresh requests are bundled together with the changes in the same batchrequest. You can disable the auto refresh by calling setRefreshAfterChange(false). If the auto refresh isdisabled, the application has to take care of refreshing the respective bindings.

    oModel.setRefreshAfterChange(false);

Concurrency Control and ETags

OData uses HTTP ETags for optimistic concurrency control. The service must be configured toprovide them. The ETag can be passed within the parameters map for every CRUDrequest. If no ETag is passed, the ETag of the cached entity is used, if it isloaded already.

XSFR Token

To address cross-site request forgery, an OData service may require XSRF tokens for changerequests by the client application. In this case, the client has to fetch a tokenfrom the server and send it with each change request to the server. The OData modelfetches the XSRF token when reading the metadata and then automatically sends itwith each write request header. If the token is no longer valid, a new token can befetched by calling the refreshSecurityToken function on the ODatamodel. The token is fetched with a request to the service document. To ensuregetting a valid token, make sure that the service document isnot cached.

Refreshing the Model

The refresh function refreshes all data within an ODatamodel. Each binding reloads its data from the server. For listor element bindings, a new request to the back end is triggered.If the XSRF token is no longer valid, it has to be fetched againwith a read request to the service document.Data that has been imported via manual CRUD requests isnot reloaded automatically.

Batch Processing

The v2.ODataModel supports batch processing($batch) in two different ways:

  • Default: All requests in a thread are collected and bundled in batchrequests, meaning that request is sent in a timeout immediately after thecurrent call stack is finished. This includes all manual CRUD requests aswell as requests triggered by a binding.

  • The requests are stored and can be submitted with a manualsubmitChanges() call by the application. This alsoincludes all manual CRUD requests as well as requests triggered by abinding.

The model cannot decide how to bundle the requests. For this, SAPUI5 provides thebatchGroupId. For each binding and each manual request, abatchGroupId can be specified. All requests belonging to thesame group are bundled into one batch request. Request without abatchGroupId are bundled in the default batch group. You canuse a changeSetId for changes. The same principle applies: Eachchange belonging to the same changeSetId is bundled into onechangeSet in the batch request. Per default, all changes havetheir own changeSet. For more information, see the APIreference.

You can use the setDeferredBatchGroups() method to seteach batchGroup to deferred: All requestsbelonging to the batchGroup are then stored ina request queue. The deferred batch group must then be submittedmanually by means of the submitChanges()method. If you do not specify a batch groupID when calling submitChanges, all deferredbatch groups are submitted.

Example:

var oModel = new sap.ui.model.odata.v2.ODataModel(myServiceUrl);

Pass the batchGroupId to a binding:

{path:"/myEntities", parameters: {batchGroupId: "myId"}}

Set the batchGroupId to deferred:

oModel.setDeferredBatchGroups(["myGroupId", "myGroupId2"]);

Submit a deferred batchGroup:

oModel.submitChanges({batchGroupId: "myGroupId", success: mySuccessHandler, error: myErrorHandler});

Two-way Binding

The v2.ODataModel enables two-way binding. Per default, all changes arecollected in a batch group called "changes" which is set to deferred. To submit thechanges, use submitChanges(). The data changes are made on a datacopy. This enables you to reset the changes without sending a new request to thebackend to fetch the old data again. With resetChanges() you canreset all changes. You can also reset only specific entities by callingresetChanges with an array of entity paths.

Note

Filtering and sorting is not possible if two-way changes are present as thiswould cause inconsistent data on the UI. Therefore, before you carry out sortingor filtering, you have to submit or reset the changes.

You can collect the changes for different entities or types in different batchgroups. To configure this, use the setChangeBatchGroups() method ofthe model:

var oModel = new sap.ui.model.odata.v2.ODataModel(myServiceUrl);oModel.setDeferredBatchGroups(["myGroupId", "myGroupId2"]);oModel.setChangeBatchGroups({ "EntityTypeName": { batchGroupId: "myGroupId", [changeSetId: "ID",] [single: true/false,] });oModel.submitChanges({batchGroupId: "myGroupId", success: mySuccessHandler, error: myErrorHandler});

To collect the changes for all entity types in the same batch group, use '*’ asEntityType. If the change is not set to deferred, the changesare sent to the backend immediately. By setting the singleparameter for changeSet to true or false, you define if a change isassigned its own change set (true) or if all changes are collectedin one change set (false). The model only takes care of thechangeSetId if single is set tofalse.

Note

The first change of an entity defines the order in the change set.

Example

Reset changes:

var oModel = new sap.ui.model.odata.v2.ODataModel(myServiceUrl);//do a changeoModel.setProperty("/myEntity(0)", oValue);//reset the changeoModel.resetChanges(["/myEntity(0)"]);

Binding-specific Parameters

The OData protocol specifies different URL parameters. You can use these parameters inbindings in addition to the parameters described above:

  • Expand parameter

    The expand parameter allows the application to read associated entitieswith their navigation properties:

    oControl.bindElement("/Category(1)", {expand: "Products"}); oTable.bindRows({ path: "/Products", parameters: {expand: "Category"}});

    In this example, all products of "Category(1)" areembedded inline in the server response and loaded in onerequest. The category for all"Products" is embedded inline inthe response for each product.

  • Select parameter

    The select parameter allows the application to define a subset ofproperties that is read when requesting an entity.

    oControl.bindElement("/Category(1)", {expand: "Products", select: "Name,ID,Products"}); oTable.bindRows({ path: "/Products", parameters: {select: "Name,Category"}});

    In this example, the properties Name, ID andofCategory(1) as well as all properties of the embeddedproducts are returned. The properties Name andCategory are included for each product. TheCategory property contains a link to the relatedcategory entry.

  • Custom query options

    You can use custom query options as input parameters for service operations. When creatingthe aggregation binding, specify these custom parameter as follows:

    oTable.bindRows({ path: "/Products", parameters: { custom: { param1: "value1", param2: "value2" } }, template: rowTemplate});

    If you use bindElement, you can specify custom parameters as follows:

    oTextField.bindElement("/GetProducts", { custom: { "price" : "500" }});

Function Import

The ODataModel supports the invoking of function imports or actions by thecallFunctionmethod:

oModel.callFunction("/GetProductsByRating",{method:"GET", urlParameters:{"rating":3}, success:fnSuccess, error: fnError})

Ifthe callFunction request is deferred, it can be submitted via the submitChangesmethod.

Note

Only "IN" parameters of function imports are currently supported.

Binding of Function Import Parameters

OData Model V2 supports the binding against function import parameters. This is similar to the createEntry methodwhich supports binding against entity properties. The callFunction method returns a request handle that has apromise. This promise is resolved when the context to which it is bound is createdsuccessfully or is rejected ifnot:

var oHandle = oModel.callFunction("/GetProductsByRating", {urlParameters: {rating:3}});oHandle.contextCreated().then(function(oContext) { oView.setBindingContext(oContext);});

If the function import returns result data, then the result data can be accessed and bound against in the $resultproperty using thecontext:

<form:SimpleForm> <core:Title text="Parameters" /> <Label text="Rating" /> <Input value="{rating}" /> <Button text="Submit" press=".submit" /> <core:Title text="Result" /> <List items="{$result}"> <StandardListItem title="{Name}" /> </List></form:SimpleForm>
Instantiating an OData Model (2024)
Top Articles
Latest Posts
Article information

Author: Jamar Nader

Last Updated:

Views: 6056

Rating: 4.4 / 5 (75 voted)

Reviews: 90% of readers found this page helpful

Author information

Name: Jamar Nader

Birthday: 1995-02-28

Address: Apt. 536 6162 Reichel Greens, Port Zackaryside, CT 22682-9804

Phone: +9958384818317

Job: IT Representative

Hobby: Scrapbooking, Hiking, Hunting, Kite flying, Blacksmithing, Video gaming, Foraging

Introduction: My name is Jamar Nader, I am a fine, shiny, colorful, bright, nice, perfect, curious person who loves writing and wants to share my knowledge and understanding with you.