Conventions for OData Metadata¶
CSDL XML Metadata¶
The service generator tool requires as input an OData Common Schema Definition Language (CSDL) XML metadata file (for OData version 2.0 or 4.0). OData version 4.0 is recommended, unless it is necessary to accommodate clients that use pre-4.0 OData frameworks.
The metadata in the CSDL XML document defines a data model for the business objects upon which the OData service will operate.
The following conventions facilitate the generation and deployment of OData services that are compatible with the Server OData API (the Java class library that supports the implementation of the generated OData services), as well as to ensure the smooth interoperability of the generated services with a variety of OData client frameworks and SDKs.
-
Use the file extension
.csdl.xml
for OData CSDL XML files. When using SAP Business Application Studio, files with this extension can be viewed or edited with the graphicalCSDL Editor
, accessed via the context menu. -
For OData 4.0 models, include the
xmlns:xsi
andxsi:schemaLocation
attributes in theedmx:Edmx
root element, as shown in the following example, to enable enhanced CSDL editing if you have installed the XML Language Support by Red Hat extension for Visual Studio Code. -
For the Schema Namespace, consider using Java package naming conventions or .NET Namespace Conventions.
-
For the EntityContainer Name, provide a name that describes the service, such as
BankService
,ShopService
etc. -
Use Upper Camel Case for naming types and properties, e.g.
TravelAgency
. -
Use singular names for complex/entity types, e.g.
Address
,Customer
. -
Use plural names for entity sets, e.g.
Customers
, or use theSet
suffix, e.g.CustomerSet
. -
Avoid using property/type names that differ only in case (e.g.
customer
andCustomer
) or that differ only in the absence/presence of underscores (e.g.Customer
and_Customer
). -
For key property names, use the
ID
suffix appended to the entity type name, e.g.CustomerID
for entity typeCustomer
. -
To support automatic server-side key generation for primary keys, it is recommended that you use non-composite numeric keys of type
Edm.Int64
. If you are certain that 32-bit integer keys are sufficient, then useEdm.Int32
. If in any doubt, then use 64-bit integer keys. You can also use typeEdm.Decimal
for key properties, but is likely to use more space in the database thanEdm.Int64
. -
You can also use the
Edm.Guid
andEdm.String
key types, but they are not recommended because they will take up more space within the database. If you use typeEdm.String
, then specifyMaxLength="36"
to ensure that the key column will be large enough to contain a generated GUID. String-typed properties containing database-generated sequence numbers are not supported. -
Properties of type
Edm.Binary
andEdm.String
should include theMaxLength
facet unless they are intentionally of unbounded length. This ensures an optimal selection of database column type (e.g.varbinary
versusblob
,varchar
versusclob
). It is assumed thatMaxLength
for strings specifies the number of Unicode code points, which may result in4*MaxLength
being used as a database column length if the database usesUTF-8
column encoding. -
Properties of type
Edm.Decimal
should specifyScale
andPrecision
facets. This ensures an optimal selection of database column type. Note that an unspecified scale defaults to zero (only integer values can be stored in the database column ifScale
is unspecified). -
Use an explicit
Nullable
facet for properties. Since the default for OData CSDL XML isNullable="true"
, it is easy to accidentally have nullable properties. Accidental nullability of properties may be a burden to client application developers, especially when using languages such as Kotlin and Swift that have strong support for nullable types. It may result in client developers having to defensively program against the possibility of properties having null values when it was not intended. -
Primary keys embedded within complex-typed properties are not currently supported.
-
Foreign keys embedded within complex-typed properties are not currently supported.
-
Stream properties embedded within complex-typed properties are not currently supported.
-
Navigation properties embedded within complex-typed properties are not currently supported.
-
Bidirectional relationships (with navigation properties in both directions) are preferred.
-
Foreign keys (specified with
ReferentialConstraint
) should be used wherever applicable. This permits the automatic implementation of OData features such as:$expand
queries, deep insert, bind operations, and link operations. -
Use
OnDelete Action="Cascade"
for navigation properties where the deletion of a parent entity should cascade to automatic deletion of the related child entities. -
Use
OnDelete Action="None"
for navigation properties where the deletion of a parent entity should be restricted (disallowed) when there are still existing related child entities. -
Use the
Core.Immutable
annotation for any properties that cannot be changed after an entity is created. SeeCustomer
andDateOfBirth
in the example below. -
Use
Validation
annotations to express simple declarative validation rules. SeeOrder/Quantity
in the example below. Currently, such validation annotations might be utilized by client frameworks, but the server runtime does not itself enforce them. Use entity listeners for server-side enforcement of validation rules.
Example Document¶
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docs.oasis-open.org/odata/ns/edmx http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edmx.xsd http://docs.oasis-open.org/odata/ns/edm http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edm.xsd">
<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml">
<edmx:Include Namespace="Org.OData.Core.V1" Alias="Core"/>
</edmx:Reference>
<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Validation.V1.xml">
<edmx:Include Namespace="Org.OData.Validation.V1" Alias="Validation"/>
</edmx:Reference>
<edmx:DataServices>
<Schema Namespace="example" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="Self">
<ComplexType Name="Address">
<Property Name="Number" Type="Edm.String" MaxLength="100" Nullable="true"/>
<Property Name="Street" Type="Edm.String" MaxLength="100" Nullable="true"/>
<Property Name="City" Type="Edm.String" MaxLength="100" Nullable="false"/>
<Property Name="Region" Type="Edm.String" MaxLength="100" Nullable="true"/>
<Property Name="Country" Type="Edm.String" MaxLength="100" Nullable="true"/>
<Property Name="PostalCode" Type="Self.PostalCode" Nullable="true"/>
</ComplexType>
<ComplexType Name="PostalCode">
<Property Name="AreaCode" Type="Edm.String" MaxLength="2" Nullable="false"/>
<Property Name="DistrictCode" Type="Edm.String" MaxLength="2" Nullable="false"/>
<Property Name="SectorCode" Type="Edm.String" MaxLength="1" Nullable="false"/>
<Property Name="UnitCode" Type="Edm.String" MaxLength="2" Nullable="false"/>
</ComplexType>
<EntityType Name="Customer">
<Annotation Term="Core.Description" String="Customer entity type"/>
<Key>
<PropertyRef Name="CustomerID"/>
</Key>
<Property Name="CustomerID" Type="Edm.Int64" Nullable="false">
<Annotation Term="Core.Description" String="Customer primary key"/>
</Property>
<Property Name="Name" Type="Edm.String" MaxLength="100" Nullable="false"/>
<Property Name="HomeAddress" Type="Self.Address" Nullable="false"/>
<Property Name="WorkAddress" Type="Self.Address" Nullable="true"/>
<Property Name="PlaceOfWork" Type="Edm.String" MaxLength="100" Nullable="false"/>
<Property Name="DateOfBirth" Type="Edm.Date" Nullable="false">
<Annotation Term="Core.Immutable"/>
</Property>
<NavigationProperty Name="Orders" Type="Collection(Self.Order)" Partner="Customer">
<OnDelete Action="Cascade"/>
</NavigationProperty>
</EntityType>
<EntityType Name="Order">
<Annotation Term="Core.Description" String="Order entity type"/>
<Key>
<PropertyRef Name="OrderID"/>
</Key>
<Property Name="OrderID" Type="Edm.Int64" Nullable="false">
<Annotation Term="Core.Description" String="Order primary key"/>
</Property>
<Property Name="CustomerID" Type="Edm.Int64" Nullable="true"/>
<Property Name="Product" Type="Edm.String" MaxLength="100" Nullable="false"/>
<Property Name="Quantity" Type="Edm.Int32" Nullable="false">
<Annotation Term="Validation.Minimum" Decimal="1"/>
</Property>
<NavigationProperty Name="Customer" Type="Self.Customer" Nullable="true" Partner="Orders">
<ReferentialConstraint Property="CustomerID" ReferencedProperty="CustomerID"/>
</NavigationProperty>
</EntityType>
<EntityContainer Name="ExampleService">
<EntitySet Name="Customers" EntityType="Self.Customer">
<Annotation Term="Core.Description" String="Customers entity set"/>
<NavigationPropertyBinding Path="Orders" Target="Orders"/>
</EntitySet>
<EntitySet Name="Orders" EntityType="Self.Order">
<Annotation Term="Core.Description" String="Orders entity set"/>
<NavigationPropertyBinding Path="Customer" Target="Customers"/>
</EntitySet>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Annotation Terms¶
OData 4.0 defines various standard
annotation terms such
An annotation term as the Core.Description
term, which can be used to annotate any CSDL metadata element with a description.
In general, annotation terms provide for metadata extensibility.
Standard annotation term definitions are grouped together in standard annotation vocabularies.
Custom Vocabularies¶
The service generator tool defines various custom annotation vocabularies. Each custom vocabulary defines a number of annotation terms. You can use these custom annotation terms to annotate CSDL model elements to enable various features for the generated OData service.
The following sections describe each of the custom annotation vocabularies.
Note
All examples use OData 4.0 syntax, but the service generator tool allows OData 4.0 annotations to be used within CSDL XML files for all supported OData versions (2.0, 3.0, and 4.0).
Note
All custom annotation terms defined by the following vocabularies that can be applied to an entity type can also be applied (instead) to an entity set. OData permits multiple entity sets to share the same entity type. However such sharing of an entity type by multiple entity sets is uncommon in practice, so it is recommended to annotate entity types rather than annotating entity sets.
Cache Vocabulary¶
To use terms within the Cache
vocabulary include a Reference
element for the com.sap.cloud.server.odata.cache.v1
namespace.
This vocabulary defines terms for configuration of caching within a cache databases.
Example:
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docs.oasis-open.org/odata/ns/edmx http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edmx.xsd http://docs.oasis-open.org/odata/ns/edm http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edm.xsd">
<edmx:Reference Uri="vocabularies/com.sap.cloud.server.odata.cache.v1.xml">
<edmx:Include Namespace="com.sap.cloud.server.odata.cache.v1" Alias="Cache"/>
</edmx:Reference>
...
</edmx:Edmx>
Security Vocabulary¶
To use terms within the Security
vocabulary include a Reference
element for the com.sap.cloud.server.odata.security.v1
namespace.
This vocabulary defines terms for annotating elements with required security roles.
Example:
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docs.oasis-open.org/odata/ns/edmx http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edmx.xsd http://docs.oasis-open.org/odata/ns/edm http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edm.xsd">
<edmx:Reference Uri="vocabularies/com.sap.cloud.server.odata.security.v1.xml">
<edmx:Include Namespace="com.sap.cloud.server.odata.security.v1" Alias="Security"/>
</edmx:Reference>
...
</edmx:Edmx>
SQL Vocabulary¶
To use terms within the SQL
vocabulary include a Reference
element for the com.sap.cloud.server.odata.sql.v1
namespace.
This vocabulary defines terms relating to the underlying SQL database used by the generated OData service for entity storage.
Example:
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docs.oasis-open.org/odata/ns/edmx http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edmx.xsd http://docs.oasis-open.org/odata/ns/edm http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edm.xsd">
<edmx:Reference Uri="vocabularies/com.sap.cloud.server.odata.sql.v1.xml">
<edmx:Include Namespace="com.sap.cloud.server.odata.sql.v1" Alias="SQL"/>
</edmx:Reference>
...
</edmx:Edmx>