This API is used to interrogate the metadata from the service metadata document of the OData provider. Both the dynamic API and proxy classes use this API for their functionality. When an application uses this API, it is usually because it needs to discover the data model at run time for a number of very specific use cases.
The API maps closely to what is within a service metadata document also known as the Common Schema Definition Language (CSDL) document. Therefore, as long as the items and their relationships in the CSDL for a particular version of OData is understood, usage of the API follows naturally.
Metadata API are found in the
Metadata may be loaded online as the application starts or embedded within the generated classes based on a supplied XML document. Once loaded by the Metadata API, it resides in memory and can be interrogated by the application. The generic class,
DataService, returns an instance of CsdlDocument using the
getMetadata method. It is from this CsdlDocument instance that we can go through the data model.
CsdlDocument csdlDocument = dataService.getMetadata();
val csdlDocument = dataService.metadata
The CSDL document has a hierarchical structure that includes entity containers as the logical containers of entity sets and service operations.
Unless you are sure that there is only one entity container in the service metadata document, it is recommended that you start the metadata interrogation through the entity container. With OData v2 and v3, there can be multiple entity containers within a service metadata document and one of those is marked as the default container. Containers can be accessed from the CSDL document as follows:
EntityContainer container = csdlDocument.getDefaultContainer();
val container = csdlDocument.defaultContainer
We can also access the entity container using its qualified name,
<namespace>.<container name>; for example,
EntityContainerMap containerMap = csdlDocument.getEntityContainers(); EntityContainer container = containerMap.get("ODataAPI.EventService");
val containerMap = csdlDocument.entityContainers val container = containerMap.get("ODataAPI.EventService")
While entity sets are defined within an entity container, the CsdlDocument instance has a map of all the entity sets from all the containers. You can get the entity set directly from the CsdlDocument instance or by using a container.
1 2 3 4
//from default container EntitySet eventSet = csdlDocument.getEntitySet("Events"); //OR from EventService container EntitySet eventSet = csdlDocument.getEntitySet("EventService.Events");
1 2 3 4
//from default container val eventSet = csdlDocument.getEntitySet("Events") //OR from EventService container val eventSet = csdlDocument.getEntitySet("EventService.Events")
getEntitySet method can handle both qualified name and local name. On the other hand, if you want to make sure the entity set being retrieved is within the container, use the following:
1 2 3
EntityContainer container = csdlDocument.getDefaultContainer(); EntitySetMap entitySetMap = container.getEntitySets(); EntitySet eventSet = entitySetMap.get("Events");
1 2 3
val container = csdlDocument.defaultContainer val entitySetMap = container.entitySets val eventSet = entitySetMap.get("Events")
Each CSDL document has within it the definition of each entity type. Therefore, it is possible to get the map of all entity types defined within the document. The entity type is retrieved using the qualified name, which consists of the namespace and the entity type name.
If there is no entity for the name specified when using the
getEntityType method using the CsdlDocument, an undefined error is thrown.
EntityTypeMap entityTypeMap = csdlDocument.getEntityTypes(); EntityType eventType = entityTypeMap.get("ODataAPI.Event");
val entityTypeMap = csdlDocument.entityTypes val eventType = entityTypeMap.get("ODataAPI.Event")
EntityType eventType = csdlDocument.getEntityType("ODataAPI.Event");
val eventType = csdlDocument.getEntityType("ODataAPI.Event")
You can also start from the container by looking for the entity set containing the entity type and then getting the entity type as follows:
1 2 3 4 5
EntityContainer container = csdlDocument.getDefaultContainer(); EntitySetMap entitySetMap = container.getEntitySets(); EntitySet eventSet = entitySetMap.get("Events"); // Get entity type for entity set Events EntityType eventType = event.getEntityType();
1 2 3 4 5
val container = csdlDocument.defaultContainer() val entitySetMap = container.entitySets val eventSet = entitySetMap.get("Events") // Get entity type for entity set Events val eventType = eventSet.entityType
Following the OData v4 nomenclature, properties are either structural or navigational. Both types are contained within the same property map returned by the entity type.
1 2 3 4 5 6 7 8
PropertyMap properties = eventType.getPropertyMap(); // structural property Property nameProp = properties.get("Name"); assertTrue(nameProp.isStructural()); // navigation property Property sessionsProp = properties.get("Sessions"); assertTrue(sessionsProp.isNavigation()); assertTrue(sessionsProp.isList());
1 2 3 4 5 6 7 8
val propertyMap = eventType.getPropertyMap() // structural property val nameProp = propertyMap.get("Name") assertTrue(nameProp.isStructural()) // navigation property val sessionsProp = propertyMap.get("Sessions") assertTrue(sessionsProp.isNavigation()) assertTrue(sessionsProp.isList())
Since the SDK is based on the OData v4 specification, associations and association sets are no longer available. You can instead determine if a navigation property is referring to multiple instances or a single instance by using the
In most cases, you are not likely to need to use the Metadata API when creating your applicaations. You can look up entity sets, entity types, and properties using the proxy classes or the dynamic API as long as you have a prior knowledge of the data model. For example, you will need to know the name of the entity set to look it up.
The Metadata API can support discovery of the data model at runtime. There is no need to know any of the names. Instead, you can start from the entity container, iterate through all the entity sets, examine the entity type associated with the entity set, and visit all the properties of the entity type.
Refer to Appendix C for the code fragment iterating through all the entity sets and retrieving from the provider every collection. For each entity set it uses the corresponding entity type to get as string the values of its structural properties. add link