Entity Framework Core: private or protected navigation properties

silent_coder picture silent_coder · May 31, 2017 · Viewed 7.9k times · Source

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; }  
}

Answer

Tseng picture Tseng · May 31, 2017

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.