Search code examples
c#asp.net-core.net-coreentity-framework-corenavigation-properties

Entity Framework Core: private or protected navigation properties


Is it somehow possible to define navigation properties in EFCore with private or protected access level to make this kind of code work:

class Model {
   public int Id { get; set; }
   virtual protected ICollection<ChildModel> childs { get; set; }  
}

Solution

  • You have two options, using type/string inside the model builder.

    modelBuilder.Entity<Model>(c =>
        c.HasMany(typeof(Model), "childs")
            .WithOne("parent")
            .HasForeignKey("elementID");
    );
    

    Not 100% sure it works with private properties, but it should.

    Update: Refactoring-safe version

    modelBuilder.Entity<Model>(c =>
        c.HasMany(typeof(Model), nameof(Model.childs)
            .WithOne(nameof(Child.parent))
            .HasForeignKey("id");
    );
    

    Or use a backing field.

    var elementMetadata = Entity<Model>().Metadata.FindNavigation(nameof(Model.childs));
        elementMetadata.SetField("_childs");
        elementMetadata.SetPropertyAccessMode(PropertyAccessMode.Field);
    

    Alternatively try that with a property

    var elementMetadata = Entity<Model>().Metadata.FindNavigation(nameof(Model.childs));
        elementMetadata.SetPropertyAccessMode(PropertyAccessMode.Property);
    

    Be aware, as of EF Core 1.1, there is a catch: The metadata modification must be done last, after all other .HasOne/.HasMany configuration, otherwise it will override the metadata. See Re-building relationships can cause annotations to be lost.