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.