-
Notifications
You must be signed in to change notification settings - Fork 92
Description
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:
EFCore.NamingConventions/EFCore.NamingConventions/Internal/NameRewritingConvention.cs
Line 207 in e3e34f9
| // 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.