efcore icon indicating copy to clipboard operation
efcore copied to clipboard

Foreign key not matched when InversePropertyAttribute is used to de-ambiguate two relationships

Open ajcvickers opened this issue 2 years ago • 1 comments

In the following code, a FeaturedPostId1 shadow property is created.

using var context = new SomeDbContext();
Console.WriteLine(context.Model.ToDebugString());

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

    public List<Post> Posts { get; } = new();

    public int FeaturedPostId { get; set; }
    public Post FeaturedPost { get; set; }
}

public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; }

    [InverseProperty("Posts")]
    public Blog Blog { get; init; }
}

public class SomeDbContext : DbContext
{
    public DbSet<Blog> Blogs => Set<Blog>();
    public DbSet<Post> Posts => Set<Post>();

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer(@"Data Source=(LocalDb)\MSSQLLocalDB;Database=AllTogetherNow")
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();
    }
}
Model:
  EntityType: Blog
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      FeaturedPostId (int) Required
      FeaturedPostId1 (no field, int) Shadow Required FK Index
    Navigations:
      FeaturedPost (Post) ToPrincipal Post
      Posts (List<Post>) Collection ToDependent Post Inverse: Blog
    Keys:
      Id PK
    Foreign keys:
      Blog {'FeaturedPostId1'} -> Post {'Id'} ToPrincipal: FeaturedPost Cascade
    Indexes:
      FeaturedPostId1
  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      BlogId (int) Required FK Index
    Navigations:
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade
    Indexes:
      BlogId

ajcvickers avatar Feb 26 '23 10:02 ajcvickers

Also happens with this model, which only contains a single relationship:

public class ContextAnnotated0 : Context101
{
    public class Blog
    {
        public int Id { get; set; }
        public int AlternateId { get; set; }

        [InverseProperty("Blog")]
        public ICollection<Post> Posts { get; } = new List<Post>();
    }

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

        [ForeignKey("Blog")]
        public int? BlogId { get; set; }

        [InverseProperty("Posts")]
        [ForeignKey("BlogId")]
        public Blog Blog { get; set; }
    }

    public DbSet<Blog> Blogs
        => Set<Blog>();

    public DbSet<Post> Posts
        => Set<Post>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
        => modelBuilder.Entity<Blog>()
            .HasMany(e => e.Posts)
            .WithOne(e => e.Blog)
            .HasPrincipalKey(e => e.AlternateId);
}

ajcvickers avatar Feb 27 '23 10:02 ajcvickers