1

Background

I'm using code first with mapping classes in EF Core at my current project. One of my entities, Action is an abstract class that has multiple inheritors ActionOne, ActionTwo, and ActionThree. I'm using TPH with an enum discriminator ActionType, which has values starting with 1 and up (it's important for later on).

Entities:

public abstract class Action
{
     public DateTime OccurredOn { get; set; }

     public virtual User User { get; set; }
}

public class ActionOne : Action
{
     public int Count { get; set; }
}

public class ActionTwo : Action
{
     public string Text { get; set; }
}

public class ActionThree : Action
{
     public double Value { get; set; }
}

public enum ActionType
{
     One = 1,
     Two = 2,
     Three = 3
}    

Mappings:

public void Configure(EntityTypeBuilder<Action> builder)
{
    builder.ToTable("Actions", "dbo")
        .HasDiscriminator<ActionType>("ActionType")
        .HasValue<ActionOne>(ActionType.One)
        .HasValue<ActionTwo>(ActionType.Two)
        .HasValue<ActionThree>(ActionType.Three);

    // Indexes 

    // Properties
    builder.Property<ActionType>("ActionType")
        .HasColumnName("ActionType");
    builder.Property(t => t.OccurredOn)
           .HasColumnName("OccurredOn")
           .IsRequired();
    builder.Property<int>("UserID")
        .HasColumnName("UserID");

    // Relationships
    builder.HasOne(t => t.User)
           .WithMany()
           .HasForeignKey("UserID")
           .IsRequired();

    // Primary Key
    builder.HasKey("ActionType", "UserID", "OccurredOn");

}

The Issue

When instantiating a new Action entity, adding it to the context and saving it - the persisted record has ActionType of 0 (the default value for the enum), which causes a conflict in the primary key and those entities could never be retrieved.

Usage Example:

var action1 = new ActionOne
{
    User = user,
    OccurredOn = DateTime.UtcNow,
    Count = count
};

dbContext.Set<Action>().Add(action1);

dbContext.SaveChanges();

Attempts So Far...

I've tried removing the shadow properties, as well as changing the order of the mapping statements. I am not interested in exposing the ActionType as a property and haven't tried it either.

I am pretty certain that the issue is a double usage of the ActionType discriminator as a primary key, but I'm not sure if there's any mapping statements I'm missing to make it work, or it's plainly a bug.

As a workaround, I've added an ID identity column and set it the primary key, which solved the problem quick enough.

I figured I will raise the question here to see if any subject matter experts can solve my mystery.

Shay
  • 1,680
  • 2
  • 26
  • 39

0 Answers0