【问题标题】:How should I model my tables so they work well with Entify Framework?我应该如何为我的表建模,以便它们与 Entity Framework 一起工作?
【发布时间】:2015-06-02 08:53:08
【问题描述】:

所以我正在尝试使用实体框架(代码优先)对以下内容进行建模。

public class School
{
    public string Name { get; set; }

    public IEnumerable<Class> Classes { get; set; }
}

public class Class
{
    public string Name { get; set; }

    public TypeOfClass Type { get; set; }

    public IEnumerable<Student> Students { get; set; } 
}

public enum TypeOfClass
{
    Kindergarten,
    HighSchool
}

public class Student
{
    public string Name { get; set; }
}

public class Kid : Student
{
    public string FavouriteToy { get; set; }
}

public class Teenager : Student
{
    public int AmountOfAcne { get; set; }
}

我想知道我应该如何为我的实体(和表)建模,以便我可以做这样的事情来选择School 中的所有Students:

var school = new School();

var kindergartenClass = new Class
{
    Name = "Kindergarten",
    Type = TypeOfClass.Kindergarten,
    Students = new List<Kid>()
};

var highschoolClass = new Class
{
    Name = "Kindergarten",
    Type = TypeOfClass.HighSchool,
    Students = new List<Teenager>()
};

school.Classes = new List<Class> {kindergartenClass, highschoolClass};

IEnumerable<Student> students = school.Classes.SelectMany(x => x.Students);

我不想为 Kids 和 Teenagers 设置单独的表,因为它们具有不同的属性,并且只会共享公共属性的子集。

谁有好的建议? :)

【问题讨论】:

    标签: c# sql entity-framework database-design


    【解决方案1】:

    首先,您的类应该具有可以被 EF 识别为主键的属性。通常这些是不可为空的整数,名称为 Id 或 [ClassName]Id:

    public class School
    {
        public int Id { get; set; } // or SchoolId
    }
    
    public class Class
    {
        public int Id { get; set; } // or ClassId
    }
    
    public class Student
    {
        public int Id { get; set; } // or StudentId
    }
    

    您有两个选项可以将 Kids 和 Teenagers 映射到单独的表:

    • 每种类型的表 (TPT) - 基类(在本例中为 Student)获取自己的表,而 Kids 和 Teenagers 各获取一张表,其中外键关联返回到 Student 表。
    • 每个具体类型的表 (TPC) - Kid 和 Teenager 获得自己的表,并且基类中的所有属性(在本例中是 Student 类中的 Name 属性)在所有子表中重复。

    我认为您追求的是 TPC。另外,我认为您只希望儿童和青少年有桌子(而不是学生)。如果是这样,您需要将 Student 类抽象化:

    public abstract class Student
    {
        // ... 
    }
    

    您需要在您的上下文中覆盖 OnModelCreating 方法:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Kid>().Map(m =>
        {
            m.ToTable("Kids");
            m.MapInheritedProperties();
        });
    
        modelBuilder.Entity<Teenager>().Map(m =>
        {
            m.ToTable("Teenagers");
            m.MapInheritedProperties();
        });
    }
    

    【讨论】:

    • 是的,但是 TPC 和 MapInheritedProperties 存在/曾经存在问题。我现在不记得细节了,但在几个月前的代码中,我刚刚删除了那个调用。英孚 6.1.2 .
    • @Henk Holterman 我使用 EF 6.1.3 测试了这段代码,没有遇到问题。您所说的问题可能已经解决。
    • 希望如此。我会尝试重现我的问题,但不会是今天。以防万一,我会留下这张便条。
    • 由于 TPT 可能存在性能问题,我倾向于使用 TPC。但我不确定如何使用 TPC 处理 Polymormphic Associations
    【解决方案2】:

    您将需要一个 Id(键)列。集合的导航属性应该是ILIst&lt;&gt;

    public class School
    {
      // Id and SchoolId are automatically recognized
      public int SchoolId { get; set; }    
      public string Name { get; set; }
      // use an IList so that you can Add()
      public IList<Class> Classes { get; set; }
    }
    

    对于继承的类,你必须pick a TPC/TPT/TPH model

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      • 2014-10-02
      • 2010-10-01
      • 2010-09-20
      • 2022-11-15
      相关资源
      最近更新 更多