Before OData V4, every entity set must be accessed from top-level even it is in a containment relationship with other set. For example, assume a schema where Order Lines (Type: “OrderLine”, EntitySet: “OrderLines”) live within Orders (Type: “Order”, EntitySet: “Orders”). Then, Orders have an “id” member that is the key, and that OrderLines has id and OrderId (container id) members that form a composite key. There are two issues in this kind of model.

  • Deep addressing through container has redundant information, e.g. /Orders(1)/OrderLines(1,2)  (the container id, “1”, is repeated)
  • Entities are always addressable through top-level entity sets, e.g. /OrderLines(1,2)

To solve the above problems, containment navigation property (“containment” in short) is introduced in OData V4 (containment spec). Using containment, you can define an implicit entity set for each instance of its declaring entity type. The implicit set cannot be accessed from top-level. The redundant information issue will be resolved, too.

The following part will introduce how to consume containment. (Sample Code)

1. EdmModel Definition

The containment navigation property should be defined it in EdmMode before consuming. There are two difference between the definitions of containment navigation property and non-containment navigation property.

  • The “ContainsTarget” attribute is set to true when it is containment. If no value is assigned to the “ContainsTarget” attribute, the attribute defaults to false.
  • No need to call Edm API AddNavigationTarget to set the target set of containment navigation property. Since, an entity cannot both belong to an entity set declared within the entity container and be referenced by a containment relationship.

The following code defined a containment navigation property “ShoppingCart” of Customer, which type is “Product”.

 

In CSDL, the navigation property will be represented as:

2. Uri Parser

For containment navigation property, the segment will be parsed as NavigationPropertySegment after Uri parsing. The related code are the following

3. Write the containment entities

There are not much difference between write a containment navigation property and non-containment navigation property.

For containment navigation property whose type is a collection, the ODataFeedWriter need to be used as following.

For containment navigation property whose type is a single-value, you can use ODataEntryWriter.

4. Read the containment entities

The following is a sample client side code to read a collection of containment navigation property.