Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turning off shadow property generation

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?

like image 771
Lucas Avatar asked Jul 02 '18 00:07

Lucas


People also ask

What is shadow properties?

Shadow properties are properties that aren't defined in your . NET entity class but are defined for that entity type in the EF Core model. The value and state of these properties are maintained purely in the Change Tracker.

Was created in shadow state because a conflicting property?

InsuranceSubjectID1' was created in shadow state because a conflicting property with the simple name 'InsuranceSubjectID' exists in the entity type, but is either not mapped, is already used for another relationship, or is incompatible with the associated primary key type.

How do I set a foreign key in EF core?

If you want the foreign key to reference a property other than the primary key, you can use the Fluent API to configure the principal key property for the relationship. The property that you configure as the principal key will automatically be set up as an alternate key.

How do you set a foreign key in an entity?

The [ForeignKey(name)] attribute can be applied in three ways: [ForeignKey(NavigationPropertyName)] on the foreign key scalar property in the dependent entity. [ForeignKey(ForeignKeyPropertyName)] on the related reference navigation property in the dependent entity.


1 Answers

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.

like image 62
Ivan Stoev Avatar answered Sep 19 '22 23:09

Ivan Stoev