实体框架6.1判别器TPH

时间:2014-07-18 21:10:26

标签: c# entity-framework inheritance downcast

我希望使用EF6实现Table-per-Hierarchy,类似于此处的说明: example

我有一个 User 的抽象基类,其中包含以下派生类型:

  • 学生
  • 联系
  • 讲师

当我检查数据库表 Users 时,当我将学生对象传递到时, discriminator 列值为(未定义)保存方法如下。相反,我希望价值是学生。否则,我的数据会在用户学生表中正确保存。

在解决问题时,我向类添加了一个UserType枚举器Get属性,以确保我从 User 转换为 Student

在我的 UserRepository 类中,我的保存方法如下所示。

    public void Save(User user)
    {
      if (Exists(user.Id))
        UpdateUser(user);
      else
      {
        switch (user.Role)
        {
          case UserType.Role.Base:
           _db.Users.Add(user);
            break;
          case UserType.Role.Student:
           _db.Users.Add(user as Student);
           break;
         case UserType.Role.Instructor:
           _db.Users.Add(user as Instructor);
           break;
         case UserType.Role.Contact:
           _db.Users.Add(user as Contact);
           break;
       }
     }
     _db.SaveChanges();
    }

替代方案失败

我尝试过以下代码来明确创建新的学生

    private void MapToStudent(User user)
    {
     _db.Users.Add(new Student()
     {
       FirstName = user.FirstName,
       LastName = user.LastName,
       //...
      });
    }

问题

我没有正确地向下倾斜?或者更确切地说,使用EF保存子类的正确/首选方法是什么?

用户基类

      public abstract class User
      {
         public int Id { get; set; }
         //...
      }

      internal class UserNotFound: User 
      { 
        public override UserType.Role Role 
        { 
          get 
            { 
             return UserType.Role.Base; 
            } 
        }
      }

      public class Student : User 
      {
         //...
         public override UserType.Role Role 
         {
           get { return UserType.Role.Student; }          
         }
      }

      public class Contact : User 
      {
         //...
         public override UserType.Role Role 
         {
           get { return UserType.Role.Contact; }          
         }
      }

      public class Instructor : User 
      {
         //...
         public override UserType.Role Role 
         {
           get { return UserType.Role.Instructor; }          
         }
      }

DatabaseContext Mapping

      public class DatabaseContext : Context
      {
          protected override void OnModelCreating(DbModelBuilder modelBuilder)
          {
              modelBuilder.Entity<Student>().ToTable("Students");
              modelBuilder.Entity<Contact>().ToTable("Contacts");
              modelBuilder.Entity<Instructor>().ToTable("Instructors");
          }
      }

1 个答案:

答案 0 :(得分:0)

TPH的映射似乎不正确。您问题中的链接示例显示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<BillingDetail>()
    .Map<BankAccount>(m => m.Requires("BillingDetailType").HasValue("BA"))
    .Map<CreditCard>(m => m.Requires("BillingDetailType").HasValue("CC"));
}

在您的问题可能如下之后建模:

  modelBuilder.Entity<User>()
    .Map<Student>(m => m.Requires("Discriminator").HasValue("STU"))
    .Map<Instructor>(m => m.Requires("Discriminator").HasValue("INS"));