Search code examples
asp.net-web-apiodatabreezejaydata

Missing inverse property in asp.net webapi odata $metadata


have very simple relationship between two entities and I am trying to expose them with asp.net webapi odata controllers but it seems that something is wrong with $metadata.

When I run jaydatasvcutil.exe on the $metadata I get warning: inverseProperty other side missing.

When I use breezejs loadNavigationProperty I get similar error.

I have the problem even with official example. http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/working-with-entity-relations

You can observe the $metadata here http://sdrv.ms/Z5Klfw

Please help.


Solution

  • When we are generating navigation properties we don't reuse the relationships.

    For example, lets say you have simple model,

    public class Product
    {
        public int Id { get; set; }
        public Supplier Supplier { get; set; }
    }
    public class Supplier
    {
        public int Id { get; set; }
        public Product[] Products { get; set; }
    }
    

    The $metadata for the navigation properties that we generate looks like this,

    <NavigationProperty Name="Supplier" Relationship="ProductsService.Models.ProductsService_Models_Product_Supplier_ProductsService_Models_Supplier_SupplierPartner" ToRole="Supplier" FromRole="SupplierPartner" />
    
    <NavigationProperty Name="Products" Relationship="ProductsService.Models.ProductsService_Models_Supplier_Products_ProductsService_Models_Product_ProductsPartner" ToRole="Products" FromRole="ProductsPartner" />
    

    Notice that we are generating two relationships instead of one. The reason we do that is that it is a hard problem to figure out if two navigation properties represent the same relationship. Take the instance of Product and Manufacturer.

    public class Manufacturer
    {
        public int Id { get; set; }
        public Product[] RawMaterials { get; set; }
        public Product[] Produces { get; set; }
    }
    public class Product
    {
        public int Id { get; set; }
        public Manufacturer[] Producers { get; set; }
        public Manufacturer[] Consumers { get; set; }
    }
    

    It is not trivial to figure out that Maufacturer.RawMaterials and Product.Consumers should share the same relationship and Manufaturer.Produces and Product.Producers should share the same relationship. We chose not to do it because the clients that we know of don't make much out of this information.

    All this happens because OData uses the same EDM model as the entityframework. Entityframework requires this information as it maps these relationships to association sets which would become tables in the database.

    Another reason we chose not to do it is that this could be going away in OData V4. Check out the working draft here (page 23 and page 57 would be of interest). In short, navigation properties in $metadata in OData V4 would look more like this,

    <NavigationProperty Name="Category" Type="Self.Category" Nullable="false" Partner="Products" />
    

    Notice that there is no relationship and there would be no association sets.