Skip to content

The plugin breaks owned collection table sharing when enabled #322

@ZzZombo

Description

@ZzZombo

Using https://efplayground.io/migrations for a quick prototype I wrote this code to make a migration:

#nullable enable
abstract class A
{
    [Key]
    public ulong Id { get; set; }
}
class B
{
    [Key]
    public ulong Id { get; set; }
    public int Qqq { get; set; }
}
class C: A
{
    public int N { get; set; }
    public virtual IList<B> B { get; set; } = [];
}
class MyDbContext : DbContext
{
    public DbSet<A> A { get; set; } = null!;

    public MyDbContext(DbContextOptions<MyDbContext> options)
        : base(options)
    {
    }
    override protected void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>();
        modelBuilder.Entity<C>(b =>
        {
            b.OwnsMany<B>(ent => ent.B, onb => onb.ToTable("A").WithOwner().HasForeignKey(e => e.Id));
            b.ToTable("A");
        });
    }
}

Run it. It works w/o a hitch. But if I copy this code verbatim into my project except for adjusting for the different naming scheme it will break with a plethora of errors when trying to generate a migration, like "Unable to create a 'DbContext' of type 'MyDbContext'. The exception 'Cannot use table 'A' for entity type 'C' since it is being used for entity type 'B' and the name 'PK_A' of the primary key {'Id'} does not match the name 'pk_a' of the primary key {'Id'}". The only difference turned out to be this plugin being active. Reading through the code, it is apparent it makes unsound assumptions about the model:

// 2. Otherwise, if the foreign key represents a collection, EF maps to a separate table. Making this owned doesn't change

I enabled the snake case naming scheme in my project. Disabling it and adjusting back the table names allows the model to be configured w/o errors as expected.

It assumes that a collection navigation to an owned type will always be placed in a new table, but it is not correct. I tried hard to work around this by making a new convention undoing the ill effects like rewritten primary keys mismatch, but I got stuck with an issue where two different owned non-unique entity types sharing the same table with the owner entity have the same named mapped property (Kind) of different types, and the plugin breaks the generation of the owner prefix for owned entity types in this scenario, so they end up with the same column name of kind instead of the usual NavPropertyName_PropertyName in snake case. I can't find the code in EF Core that assigns the column names for properties of owned types to adopt into my convention to fix them up.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions