EF6 Использовать существующий столбец БД в качестве дискриминатора - PullRequest
0 голосов
/ 23 сентября 2018

Я использую Entity Framework 6 Code First для своего проекта.У сущностей есть Наследование, поэтому я следую TPH (Таблица на Иерархию).Я прочитал следующее Статья и многие другие.

Ни один из них не объясняет, каким образом я могу использовать существующий столбец БД, сопоставленный со свойством в Базовом объекте, как дискриминатор.

Основываясь на приведенном ниже примере, я получаю следующее исключение

При генерации модели обнаружены одна или несколько ошибок проверки:

TaskType: Name: Каждое имя свойства в типе должнобыть уникальный.Имя свойства 'TaskType' уже определено.

Я думаю, что автоматически сгенерированный EF дискриминатор и сопоставление моих сущностей конфликтуют.

Существует ли возможный способ указать EF неавтоматически сгенерировать столбец и использовать столбец, сопоставленный с сущностью.Если нет, то есть ли какое-либо объяснение этому, которого нельзя избежать.

Peace.

У меня есть сущности в следующем формате

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)
        {

        }

    }
}

1 Ответ

0 голосов
/ 24 сентября 2018

Удалите TaskType из вашей сущности и позвольте EF управлять этим как часть отображения TPH.Чтобы различать типы, если вы имеете дело с коллекцией базового класса, используйте .OfType<PolishedTask>(), а не .Where(x => x.TaskType == TaskType.Polished) EF должен позаботиться об остальном.Если вы хотите, чтобы это было для сущности, создайте неотображенное свойство в ваших подклассах.Т.е.

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; }
  //}
}
...