Skip to content

TPH inheritance with two properties mapped to the same column but different nullability is not allowed #21384

Closed

Description

I'd like to model a type hierarchy using TPH inheritance where the same property exists on two derived entities and maps to the same underlying column in a SQL Server DB but has different nullability.

When I create my DbContext and model the entities, making sure I explicitly specify the column name, I end up getting a following exception at runtime:

System.InvalidOperationException : 'Derived1.Property' and 'Derived2.Property' are both mapped to column 'Property' in 'Base' but are configured with different nullability.

Steps to reproduce

Let's have entities Derived1 and Derived2, both siblings in the type hierarchy with ancestor Base and mapping to table Base with backing column named Property that allows NULL. In my scenario, the property Property is required in Derived1 but optional in Derived2. Therefore I don't model the property on Base entity, but I add the property with the same name and type to Dervied1 and Derived2. The code may look something like this:

class Base
{
}

class Derived1
{
    string Property { get; set; }
}

class Derived2
{
    string Property { get; set; }
}

class BaseMap : EntityTypeConfiguration<Base>
{
    public override void Configure(EntityTypeBuilder<Base> builder)
    {
        base.Configure(builder);

        builder.ToTable("Base");

        builder.HasDiscriminator<string>("Discriminator")
            .HasValue<Derived1>("Derived1")
            .HasValue<Derived1>("Derived2");
    }
}

class Derived1Map: IEntityTypeConfiguration<Derived1>
{
    public void Configure(EntityTypeBuilder<Derived1> builder)
    {
        builder.HasBaseType<Base>();

        builder.Property(e => e.Property).HasColumnName("Property").IsRequired(true);
    }
}

class Derived2Map : IEntityTypeConfiguration<Derived2>
{
    public void Configure(EntityTypeBuilder<Derived2> builder)
    {
        builder.HasBaseType<Base>();

        builder.Property(e => e.Property).HasColumnName("Property").IsRequired(false);
    }
}

I came across issue #17820 and its fix 218f92c where the check for different nullability was added. I opened this originally as discussion question 21366 where @AndriySvyryd kindly advised that I open and issue as this is a bug.

Just a thought - I suppose an extra complication would arise in case of nullable value types. In my case above, the property was of type string/nvarchar hence a reference type that allows nulls (we don't use nullable reference types). For example, when the property is datetime in DB as that would need to be modeled as DateTime in Derived1 (required) and DateTime? in Derived2 (optional).

Further technical details

EF Core version: 5.0.0-preview.5.20278.2 but should also be reproducible in 3.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 5 preview 5 but also .NET Core 3.1
Operating system: Windows 10 Enterprise build 18363
IDE: Visual Studio 2019 16.6.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions