我应该如何建模我的表,以便它们与Entity Framework一起使用?

时间:2015-03-29 09:35:48

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

所以我试图使用Entity Framework(代码优先)对以下内容进行建模。

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

我想知道如何对我的实体(和表格)进行建模,以便我可以做这样的事情来选择Student中的所有School

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

我不想为儿童和青少年设置单独的桌子,因为他们有不同的属性,只会共享一个子集共同的属性。

任何有良好建议的人? :)

2 个答案:

答案 0 :(得分:3)

您需要一个Id(密钥)列。集合的导航属性应为ILIst<>

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

答案 1 :(得分:3)

首先,您的类应具有可被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
}

您可以通过两种方式将儿童和青少年映射到单独的表格中:

  • 每种类型的表(TPT) - 基类(在本例中为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();
    });
}