Turning off shadow property generation

c# entity-framework entity-framework-core properties

Question

I'm having a weird issue with setting Entity Framework Core foreign keys. EF keeps adding a shadow property automatically for my property and is creating a foreign key of it.

That would be perfectly fine for me, however - I want to be able to set the foreign key delete behaviour to cascade - using that "automatic" shadow property I'm not allowed to do that.

Therefore I decided to create my own foreign key with the Fluent API:

modelBuilder.Entity<PostDataModel>(e =>
{
    // Primary key
    e.HasKey(c => c.Id);

    // Relation
    e.HasOne<PostGroupDataModel>()
        .WithMany()
        .HasForeignKey("GroupId")
        .OnDelete(DeleteBehavior.Cascade)
        .IsRequired();
});

This however, did not help much - automatically generated shadow property is still being generated for the table (GroupId1):

enter image description here

public class PostGroupDataModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Params { get; set; }

    public List<PostDataModel> Posts { get; set; }
}

public class PostDataModel
{
    public int Id { get; set; }

    public string Content { get; set; }

    public PostGroupDataModel Group { get; set; }
}

Is there a way to turn off automatic generation of the shadow property in EF Core? or at least modify the generated shadow property to delete on cascade?

1
4
7/2/2018 12:49:11 AM

Accepted Answer

The problem is not the shadow property, but the fluent configuration:

e.HasOne<PostGroupDataModel>()
    .WithMany()

By using parameterless overloads you are effectively telling EF to create relationship with no navigation properties at both ends, which it does. However, you do have navigation properties, hence EF Core creates another relationship with conventional FK property/column name. Just because the default name GroupId is already reserved for your explicit relationship it appends number to it in order to make it unique.

The solution is to always use the Has / With overloads that represent the presense / absence of a navigation property. In your case:

e.HasOne(x => x.Group)
    .WithMany(x => x.Posts)

You can keep the rest of the fluent config, but since GroupId is the default value of the FK property/column in this case, .HasForeignKey("GroupId") can be skipped. Also because the DeleteBehavior.Cascade is the default for required relationships, .OnDelete(DeleteBehavior.Cascade) can be skipped too and the only remaining could be .IsRequired(). I.e.

.HasForeignKey("GroupId") // optional
.OnDelete(DeleteBehavior.Cascade) // optional
.IsRequired();

Of course specifying them explicitly won't hurt.

6
7/2/2018 9:56:18 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow