Reputation: 56
I am using Entity Framework 6 Code First for my project. Entities have Inheritance so I am following TPH(Table per Hierarchy). I read following Article and many others.
None of them explain a way in which I can use an existing DB Column mapped to a property in Base Entity as Discriminator.
Based on the sample below I get following Exception
One or more validation errors were detected during model generation:
TaskType: Name: Each property name in a type must be unique. Property name 'TaskType' is already defined.
I think EF's auto generated Discriminator and my Entities Mapping is Conflicting.
Is there a possible way to instruct EF to not auto generate column and use Entity mapped Column. If not, is there any explanation of this can not be avoided.
Peace.
I have Entities in following format
public enum TaskType
{
Random = 0,
Polished = 1,
Dropping = 2
}
public interface ITask
{
int Id { get; set; }
string Name { get; set; }
TaskType typeofTask { get; set; }
}
public abstract class BaseTask : ITask
{
public BaseTask(string name, TaskType type)
{
this.Name = Name;
this.typeofTask = type;
}
public int Id { get; set; }
public string Name { get; set; }
public TaskType typeofTask { get; set; }
}
public class RandomTask : BaseTask
{
public RandomTask() : base("My Random", TaskType.Random)
{
}
public int Owner { get; set; }
}
public class PolishedTask : BaseTask
{
public PolishedTask() : base("My Polished", TaskType.Polished)
{
}
}
public class DBContextTest : DbContext
{
public DBContextTest(string connection) : base(connection)
{
}
public DbSet<BaseTask> Task { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BaseTask>().Map<RandomTask>(m => m.Requires("TaskType").HasValue(1))
.Map<PolishedTask>(m => m.Requires("TaskType").HasValue(1));
modelBuilder.Entity<BaseTask>().Property(p => p.typeofTask).HasColumnName("TaskType");
}
}
class Program
{
static void Main(string[] args)
{
try
{
DBContextTest dataContext = new DBContextTest("Server = (localdb)\\mssqllocaldb;DataBase = LOC2;Trusted_Connection = True;");
RandomTask randomtask = new RandomTask();
PolishedTask polishedTask = new PolishedTask();
dataContext.Task.Add(randomtask);
dataContext.Task.Add(polishedTask);
dataContext.SaveChanges();
}
catch (System.Exception ex)
{
}
}
}
Upvotes: 1
Views: 898
Reputation: 34978
Remove TaskType from your entity and let EF manage that as part of the TPH mapping. To differentiate types if you're dealing with a base-class collection, use .OfType<PolishedTask>()
rather than .Where(x => x.TaskType == TaskType.Polished)
EF should take care of the rest. If you do want it on the entity, create a non-mapped property in your sub-classes.
I.e.
public abstract class BaseTask
{
[NotMapped]
public abstract TaskType TaskType { get; }
}
public class PolishedTask
{
[NotMapped]
public override TaskType TaskType => TaskType.Polished
// or
//public override TaskType TaskType
//{
// get { return TaskType.Polished; }
//}
}
Upvotes: 1