【问题标题】:Entity Framework 6.1 Discriminator TPH实体框架 6.1 鉴别器 TPH
【发布时间】:2014-07-18 21:10:25
【问题描述】:

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

我有一个 User 的抽象基类,它具有以下派生类型:

  • 学生
  • 联系方式
  • 讲师

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

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

在我的 UserRepository 类中,我的 Save 方法如下。

    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();
    }

失败的替代方案

我已经尝试过类似下面的代码来显式创建一个新的Student

    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 映射

      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");
          }
      }

【问题讨论】:

  • 我认为问题是你的基本类型不是抽象的。
  • @ErikPhilips 我的 User 类被指定为:public abstract class User
  • 那么这段代码不应该存在:case UserType.Role.Base: _db.Users.Add(user);。但是,user.Role 的值是怎么设置的呢?
  • internal class UserNotFound: User { public override UserType.Role Role { get { return UserType.Role.Base; } } } 是我的 User 空对象的简单案例。我正在覆盖每个子类中的属性并根据其匹配的枚举值进行设置。对于@ErikPhilips
  • 为了将来参考,最好不要在评论中添加代码,而是向您的实际问题添加代码(您可以根据需要编辑它),以便其他阅读可以全面理解您的无需阅读所有 cmets 的问题。

标签: c# entity-framework inheritance downcast


【解决方案1】:

您的 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"));

【讨论】:

  • 我在 TPH 和 TPT 之间混合了我的方法,所以当我插入简单的 Administrator 类时,它使用的是 Discriminator 列,而其他子类不使用该列,而是将其数据放入单独的适当表中。 concise documentation
猜你喜欢
  • 1970-01-01
  • 2011-06-28
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2012-07-22
相关资源
最近更新 更多