.Net Core Entity Framework - Discrimator TPH

.net-core c# ef-fluent-api entity-framework-core

Question

I'm currently trying to write to a table which inherits from an abstract base class. When I try to do this I get the following error (The ContactMethod property is the discriminator):

System.Data.SqlClient.SqlException: Invalid column name 'ContactMethod'.

EmailContactDetails.cs:

public class EmailContactDetail : ContactDetail
{
    [ApiMember(Description = "The Contact Method")]
    public override ContactMethod ContactMethod => ContactMethod.Email;

    [ApiMember(Description = "Email Address")]
    public string EmailAddress { get; set; }
}

EmailContactDetailConfiguration.cs:

public class EmailContactDetailsConfiguration : IEntityTypeConfiguration<EmailContactDetail>
{
    public void Configure(EntityTypeBuilder<EmailContactDetail> builder) => Configure(builder, "dbo");

    public void Configure(EntityTypeBuilder<EmailContactDetail> builder, string schema)
    {
        builder.Property(x => x.EmailAddress).HasColumnName("EmailAddress").HasColumnType("nvarchar(255)");
    }
}

ContactDetail.cs:

public abstract class ContactDetail
{
    [ApiMember(Description = "The Identifier")]
    public Guid Id { get; set; }

    [ApiMember(Description = "The Contact Method")]
    public virtual ContactMethod ContactMethod { get; set; }
}

ContactDetailConfiguration.cs

public class ContactDetailsConfiguration : IEntityTypeConfiguration<ContactDetail>
{
    public void Configure(EntityTypeBuilder<ContactDetail> builder) => Configure(builder, "dbo");

    public void Configure(EntityTypeBuilder<ContactDetail> builder, string schema)
    {
        builder.ToTable("ContactDetails", schema);

        // Table per hierarchy. all subclasses share the same db table for performance.
        builder.HasDiscriminator(x => x.ContactMethod)
            .HasValue<EmailContactDetail>(ContactMethod.Email);

        builder.Property(x => x.Id).HasColumnName("Id").IsRequired().HasColumnType("uniqueidentifier").ValueGeneratedOnAdd();
    }
}

I've tried hiding the discriminator "ContactMethod" by adding the following to the ContactDetailConfiguration.cs file:

builder.Ignore(x => x.ContactMethod);

Once I've done that I end up with the following error

The entity type 'EmailContactDetail' is part of a hierarchy, but does not have a discriminator property configured.
1
1
4/4/2018 2:56:13 PM

Accepted Answer

You shouldn't hide the property configured as TPH discriminator from EF because it is essential for EF Core implementation of the TPH strategy.

The initial error simply indicates that your model and database are out of sync. It's true that by convention EF Core uses string shadow property and column called Discriminator. But the whole purpose of HasDiscriminator fluent API is to allow changing the discriminator property/column type, as well as mapping it to an existing property of your entity model.

Which is the case here. You've told EF Core to use your existing property ContactMethod as discriminator, hence EF Core is looking for column named ContactMethod in the database table. So to resolve the issue, simply update your database from the model (using the usual procedure when model is changed - add new migration, update database etc).

3
4/4/2018 3:11:35 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow