OData / WebApi

OData Web API: A server library built upon ODataLib and WebApi
https://docs.microsoft.com/odata
Other
856 stars 473 forks source link

ForeignKeyAttributeConvention fails when multiple properties of which one is nullable are used #1155

Open J-ohn opened 6 years ago

J-ohn commented 6 years ago

The use case that can not be handled is for example:

Page has Language, Page optionally has parent page in the same language.

Entity Framework treats this correctly.

Assemblies affected

System.Web.Http.OData >= 5.4

Reproduce steps

using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Web.Http.OData.Builder;

namespace ConsoleApp13 { class Program { static void Main(string[] args) {

        var modelBuilder = new ODataConventionModelBuilder();

        modelBuilder.EntitySet<Page>("Pages");
        modelBuilder.EntitySet<Language>("Languages");

        var model = modelBuilder.GetEdmModel();
    }
}

public class Page
{
    [Key, Column(Order = 1)]
    public int ID { get; set; }

    [Key, Column(Order = 2)]
    public int LanguageID { get; set; }

    [ForeignKey(nameof(LanguageID))]
    public Language Language { get; set; }

    public int? ParentPageID { get; set; }

    [ForeignKey(nameof(ParentPageID) + ", " + nameof(LanguageID))]
    public Page ParentPage { get; set; }
}

public class Language
{
    [Key, Column(Order = 1)]
    public int ID { get; set; }
}

}

Expected result

The above is perfectly valid in terms of database design.

Actual result

System.InvalidOperationException: 'The dependent property types 'System.Int32' are not same as the principal key types 'System.Int32,System.Int32'. The dependent and principal must each contain the same number of elements and must have the same types.'

Additional detail

ForeignKeyAttributeConvention matches properties based on type without using Nullable.GetUnderlyingType. Alternatively it could consider the whole relationship optional if one property is nullable. When having the same scenario without any required property, no constraint is added, so to be consistent this should also be treated the same way.

Workaround

Use System.Web.Http.OData < 5.4

morbidcamel101 commented 6 years ago

Any idea when this can be fixed? I ran into the issue with multi-key entities and since I use a model-first approach i'm pretty sure the generated code is fine. I downgraded my NuGet package and all seems fine so the work-around does work.