C# EF代码优先:具有多个多对一关系的实体类型

C# EF代码优先:具有多个多对一关系的实体类型,c#,entity-framework,ef-code-first,C#,Entity Framework,Ef Code First,考虑3类:个人,公司,和文件 Person和Company是完全不同和不相关的,但它们都有一组文件对象。无论它属于哪个实体,文件始终具有相同的结构 这个问题是关于如何对文件可能具有的多对一关系进行最佳建模;在这种情况下,文件可以与人员或公司建立多对一关系(但不能同时在同一实例中) 方法1: class Person { public int Id {get;set;} public ICollection<File> Files {get;set;} } class

考虑3类:
个人
公司
,和
文件

Person
Company
是完全不同和不相关的,但它们都有一组
文件
对象。无论它属于哪个实体,
文件
始终具有相同的结构

这个问题是关于如何对
文件
可能具有的多对一关系进行最佳建模;在这种情况下,
文件
可以与
人员
公司
建立多对一关系(但不能同时在同一实例中)


方法1:

class Person
{
    public int Id {get;set;}
    public ICollection<File> Files {get;set;}
}
class Company
{
    public int Id {get;set;}
    public ICollection<File> Files {get;set;}
}
class File
{
    public int Id {get;set;}
    public string Path {get;set;}
}

/* 
    EF Generates:
    -----------------
    Table: Person (Id)
    Table: Company (Id)
    Table: File (Id, Path, Person_Id, Company_Id)
*/
class Person
{
    public int Id {get;set;}
    public ICollection<PersonFile> Files {get;set;}
}
class Company
{
    public int Id {get;set;}
    public ICollection<CompanyFile> Files {get;set;}
}
class File
{
    public int Id {get;set;}
    public string Path {get;set;}
}
class PersonFile
{
    public Person Person {get;set;}
    public File File {get;set;}
}
class CompanyFile
{
    public Company Company {get;set;}
    public File File {get;set;}
}

/*
    EF Generates:
    ------------------
    Table: Person (Id)
    Table: Company (Id)
    Table: File (Id, Path)
    Table: PersonFile (Person_Id, File_Id)
    Table: CompanyFile (Company_Id, File_Id)
*/
这完成了与方法1相同的事情,并且更接近我在DB-first设计中的传统做法。但它需要两个额外的类,我真的不需要。。。还是我?我想这就是这个问题的重点


在设计代码优先实体框架应用程序时,我是否需要担心数据库模式?我是否可以将代码/模型的简单性优先于数据库设计,如方法1所示?还是应该像方法2那样,在编写类时考虑数据库设计?

是的,您确实需要担心数据库模式

在您的示例中可能没有具体说明,但在使用继承时尤其如此

这是因为关系数据库(特别是SQL)不知道继承的概念。在设计日程安排时,你必须决定哪种方法适合你的需要

例如,在创建学校数据库时,您可能会设计一个人,他有姓名、地址、电话号码等

你会发现学生和老师都有名字、地址等。与流行的观点相反,你会发现学生和老师都是人

最常用的三种继承方法

  • TPH每个层次结构的表:一个大表,用于所有派生类的Person,教师和学生的所有属性都在一个表中
  • TPT每种类型的表格:教师/学生/个人在单独的表格中。教师和学生的个人数据都有外键
  • TPC每个具体类的表:包含教师和人员属性所有数据的教师表和包含学生和人员属性所有数据的学生表
你将使用哪一个取决于共享属性的比例以及学生和教师之间的差异。如果它们几乎所有的属性都是相同的,那么只有一个表的TPH就足够了

但是,如果有很多教师没有的学生属性,那么该表将有很多教师的空值。如果没有多少老师与学生人数相比,这可能不是问题,否则浪费空间可能是一个需要考虑的项目。 另一件需要考虑的是计划会经常改变。如果您确实确信教师永远是人,并且学生和教师之间的共同属性(=人属性)永远是共同的,那么TPH可能会更好:三张表:个人/教师/学生

另一方面,如果你认为无论何时你需要一个学生,你总是需要他的个人数据,那么TPH总是会导致加入。在这种情况下,TPC可能是一个更好的选择。然而,如果您经常只需要学生的特定数据而不需要他的个人数据,那么TPC可能不是一个好的选择

如果您不关心该方案,您会发现实体框架将选择TPH:一个包含所有学生和教师的大表,其中包含学生和教师的所有属性

如果你不想要这个,你必须告诉EF你想要其他的方法之一。使用fluentapi很容易做到这一点

如何做到这一点在中有很好的描述


顺便说一下,完整的文章对我开始使用EF-code编程非常有帮助

谢谢!回复和链接都很有帮助!