Skip to content

Allow Shared Columns with ComplexType #38485

Description

@FuJa0815

Bug description

Currently, in a TPH mapped table properties of a ComplexType with the same column name do not share columns.

The code in "Your code" creates this migration:

migrationBuilder.CreateTable(
    name: "Thing",
    columns: table => new
    {
        Id = table.Column<int>(type: "INTEGER", nullable: false)
            .Annotation("Sqlite:Autoincrement", true),
        Discriminator = table.Column<string>(type: "TEXT", maxLength: 5, nullable: false),
        Address_City = table.Column<string>(type: "TEXT", nullable: true),
        Address_Street = table.Column<string>(type: "TEXT", nullable: true),
        Address_City1 = table.Column<string>(type: "TEXT", nullable: true),
        Address_Street1 = table.Column<string>(type: "TEXT", nullable: true)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Thing", x => x.Id);
    });

It should map the 4 Address columns to 2.
Workarounds:

  • Use THC or THT mapping
  • Use something like this:
public abstract class Thing
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; init; }

    [Column(nameof(Address))]
    protected Address? Address { get; set; }
}

public sealed class ThingA : Thing
{
    [NotMapped]
    public new required Address Address { get => base.Address!; set => base.Address = value; }
}
public sealed class ThingB : Thing
{
    [NotMapped]
    public new required Address Address { get => base.Address!; set => base.Address = value; }
}

Your code

public class TestContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlite($"DataSource=:memory:");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Thing>()
            .HasDiscriminator()
            .HasValue<ThingA>("A")
            .HasValue<ThingB>("B");
    }
}

[ComplexType]
public record class Address(string Street, string City);

public abstract class Thing
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; init; }
}

public sealed class ThingA : Thing
{
    [Column(nameof(Address))]
    public required Address Address { get; set; }
}
public sealed class ThingB : Thing
{
    [Column(nameof(Address))]
    public required Address Address { get; set; }
}

Stack traces


Verbose output


EF Core version

10.0.9

Database provider

No response

Target framework

.NET 10

Operating system

No response

IDE

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions