Uploaded image for project: 'OASIS Open Data Protocol (OData) TC'
  1. OASIS Open Data Protocol (OData) TC
  2. ODATA-1450

Key with PropertyRef using navigation path incompatible with Protocol 11.4.2 "Create an Entity"

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: V4.01_OS
    • Fix Version/s: V4.01_ERRATA01
    • Component/s: Protocol
    • Labels:
      None
    • Environment:

      Proposed

    • Proposal:
      Hide

      Extend examples 76 and 77 in section 11.4.2.1 Link to Related Entities When Creating an Entity to also show a to-one association:

      Example 76: using the JSON format, 4.0 clients can create a new manager entity with links to existing employees by applying the odata.bind annotation to the Manager and DirectReports navigation properties

      {
        "@odata.type":"#Northwind.Manager",
        "ID": 1,
        "FirstName": "Pat",
        "LastName": "Griswold",
        "Manager@odata.bind": "http://host/service/Employees(0)",
        "DirectReports@odata.bind": [
          "http://host/service/Employees(5)",
          "http://host/service/Employees(6)"
        ]
      }
      

      Example 77: using the JSON format, 4.01 clients can create a new manager entity with links to existing employees by including the entity-ids within the Manager and DirectReports navigation properties

      {
        "@type":"#Northwind.Manager",
        "ID": 1,
        "FirstName": "Pat",
        "LastName": "Griswold",
        "Manager": { "@id": "Employees(0)" },
        "DirectReports": [
          {"@id": "Employees(5)"},
          {"@id": "Employees(6)"}
        ]
      }
      
      Show
      Extend examples 76 and 77 in section  11.4.2.1 Link to Related Entities When Creating an Entity to also show a to-one association: Example 76: using the JSON format, 4.0 clients can create a new manager entity with links to existing employees by applying the odata.bind annotation to the Manager and DirectReports navigation properties { "@odata.type" : "#Northwind.Manager" , "ID" : 1, "FirstName" : "Pat" , "LastName" : "Griswold" , "Manager@odata.bind" : "http: //host/service/Employees(0)" , "DirectReports@odata.bind" : [ "http: //host/service/Employees(5)" , "http: //host/service/Employees(6)" ] } Example 77: using the JSON format, 4.01 clients can create a new manager entity with links to existing employees by including the entity-ids within the Manager and DirectReports navigation properties { "@type" : "#Northwind.Manager" , "ID" : 1, "FirstName" : "Pat" , "LastName" : "Griswold" , "Manager" : { "@id" : "Employees(0)" }, "DirectReports" : [ { "@id" : "Employees(5)" }, { "@id" : "Employees(6)" } ] }

      Description

      Consider this CSDL.

      <?xml version="1.0" encoding="utf-8"?>
      <edmx:Edmx Version="4.01" 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:DataServices>
              <Schema Namespace="example" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="Self">
                  <EntityType Name="Customer">
                      <Key>
                          <PropertyRef Name="ID"/>
                      </Key>
                      <Property Name="ID" Type="Edm.Int32" Nullable="false"/>
                      <NavigationProperty Name="Photo" Type="Self.CustomerPhoto" Partner="Customer">
                          <OnDelete Action="Cascade"/>
                      </NavigationProperty>
                  </EntityType>
                  <EntityType Name="CustomerPhoneNumber">
                      <Key>
                          <PropertyRef Name="Customer/ID" Alias="CustomerID"/>
                      </Key>
                      <Property Name="PhoneNumber" Type="Edm.String" Nullable="false"/>
                      <NavigationProperty Name="Customer" Type="Self.Customer" Nullable="false"/>
                  </EntityType>
                  <EntityContainer Name="CustomerService">
                      <EntitySet Name="Customers" EntityType="Self.Customer">
                          <NavigationPropertyBinding Path="Photo" Target="CustomerPhotos"/>
                      </EntitySet>
                      <EntitySet Name="CustomerPhoneNumbers" EntityType="Self.CustomerPhoneNumber">
                          <NavigationPropertyBinding Path="Customer" Target="Customers"/>
                      </EntitySet>
                  </EntityContainer>
              </Schema>
          </edmx:DataServices>
      </edmx:Edmx>
      

      If a client sends this request:

      POST /CustomerPhoneNumber
      
      {"Customer":{"ID":123},"PhoneNumber":"+18001234567"}
      

      then per Protocol 11.4.2 "Create an Entity":

      The entity representation MAY include references to existing entities as well as content for new related entities, but MUST NOT contain content for existing related entities.

      ... the above POST request MUST be interpreted as a deep insert. The client cannot portably create a CustomerPhoneNumber (except via a bind operation) as any attempt to specify its key (via the customer it relates to) will be interpreted as a deep insert.

      If we were to relax the language in section 11.4.2 to allow an interpretation of relating a CustomerPhoneNumber to an existing Customer (rather than also creating the Customer by deep insert), then the specification is now ambiguous in regard to the correct interpretation of the above example payload.

      Similar issues apply to 11.4.3.1 "Update Related Entities When Updating an Entity"

      If a nested entity has the same id or key fields as an existing entity, the existing entity is updated according to the semantics of the PUT or PATCH request.

      Using the same payload for updating an existing CustomerPhoneNumber by PUT (in an attempt to link the photo to a different Customer) would be interpreted as a deep update to PUT the newly related customer (clearing its non-key properties, if any).

      The key point of discussing the issue is to work out how to discourage implementers from treating inline relationships (with only the related entity's key) as a substitute for bind operations while at the same time not implementing bind operations the standard way.

        Attachments

          Activity

            People

            • Assignee:
              handl Ralf Handl
              Reporter:
              evan.ireland.2 Evan Ireland
            • Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated: