实体框架和加入表达式中的一对多配置

时间:2014-02-26 10:33:14

标签: c# entity-framework

我正在使用EF codefirst。我对实体中的关系感到困惑。我有两个实体StudentStandard。如下所示

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }
    public int StdandardId { get; set; }
}

public class Standard
{
    public int StandardId { get; set; }
    public string StandardName { get; set; }
    public string Description { get; set; }
}

他们有一对多的关系。 我可以通过像这样的简单连接表达式来完成这个

var list = StudentList.Join
          (StandardList,c => c.StdandardId,o => o.StandardId,(c, o) => new
          {
              StudentId = c.StudentId,
              StudentName = c.StudentName,
              StandardName = o.StandardName
          });

那我为什么要配置像一对多的关系,比如

public class Student
{
    public Student() { }
    public int StudentId { get; set; }
    public string StudentName { get; set; }
    public int StdandardId { get; set; }    
    public virtual Standard Standard { get; set; }
}

public class Standard
{
    public Standard()
    {
        Students = new List<Student>();
    }

    public int StandardId { get; set; }
    public string StandardName { get; set; }
    public string Description { get; set; }
    public virtual ICollection<Student> Students { get; set; }
}

是否有任何关键的好处。?哪一个表现不错?

2 个答案:

答案 0 :(得分:3)

导航属性(Students)是隐式连接。但它是外连接。如果您明确加入,则可以强制实施内部联接,这通常会表现得更好。如果性能至关重要,请这样做。

所以给自己两个机会。创建导航属性并在必要时显式连接。

导航属性的好处是更简洁的语法。 e.g。

from standard in Standards
select new { standard.StandardName , NrOfStudents = standard.Students.Count() })

对于此查询,您始终需要外部联接,因为您还希望报告零学生的标准。

或隐含的SelectMany

from standard in Standards
where standard.StandardId == id
from student in standard.Students
select new { student. ... }

导航属性可帮助您在没有这种详细的连接语法的情况下执行连接。

答案 1 :(得分:2)

这个问题的答案可以达到论文的大小。

我会尽力保持它必不可少。简而言之,外键用于确保参照完整性。

在你的select语句中,它可能没有什么区别,但考虑更新,插入和删除语句,以及你必须采取的障碍,以便将所有内容级联到最后一个表。

让我们假设您的外键约束设置为Cascade。无论何时对您的mastertable进行更改,都会将更改级联到每个子表。您必须手动加入语句中的每个表来实现相同的目标。

如果约束设置为Restrict,只要仍有Student引用该约束,您就无法删除Standards。同样,你必须每次在你的陈述中手工检查这一点。

你很可能会在脑海中做到这一点,但是你会犯错误,然后当资金到位时,你可能会遇到不一致的数据。


然后EF很舒服。

我可以加入我的数据,但如果有外键和tehrefore关系,我可以写

var students = context.Students.Include(o => o.Enrollments);

并在我的视图中使用

@foreach(var enrollment in Model.Enrollments)
{
   //...
}

从本质上讲,这不是纯粹与实体框架相关的问题,而是与关系数据库相关的问题。

查看ACIDForeign Keys