Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架计数效率_C#_Entity Framework - Fatal编程技术网

C# 实体框架计数效率

C# 实体框架计数效率,c#,entity-framework,C#,Entity Framework,我从数据库中查询学校实体。然后,我尝试通过这样做来获得该学校的学生人数: var school = context.schools.Where(s=>s.ID == 1).Single(); int cnt = school.students.Count(); 但我看到发送到数据库的查询得到了该学校的所有学生记录,并且计数是在应用服务器上完成的 而以下内容只是从数据库中查询COUNT(),应该是这样的: int cnt = context.students.Where(s=>s.s

我从数据库中查询学校实体。然后,我尝试通过这样做来获得该学校的学生人数:

var school = context.schools.Where(s=>s.ID == 1).Single();
int cnt = school.students.Count();
但我看到发送到数据库的查询得到了该学校的所有学生记录,并且计数是在应用服务器上完成的

而以下内容只是从数据库中查询COUNT(),应该是这样的:

int cnt = context.students.Where(s=>s.schoolID == 1).Count();
为什么这两种方法之间存在如此大的差异?第一个查询不应该也使用COUNT()来提高效率吗


注意:不查询学校实体不是一个选项,因为我正在使用它的一些字段。

school.students.Count()
通过LazyLoading工作,因此首先,您在客户端获取学生:
school.students
,然后
.Count()
。但您可以按以下方式修改代码,即执行一次数据库访问:

var answer = (from sch in context.schools
              where sch.ID == 1
              join st in context.students on sch.ID equals st.schoolID into subs
              from sub in subs.DefaultIfEmpty()
              group sub by new { sch.ID, sch.Name, sch.Location } into gr
              select new 
              {
                  gr.Key.Name,
                  gr.Key.Location,
                  Count = gr.Count(x => x != null)
              }).First();

sch.Name
sch.Location
-需要进一步使用的学校字段

查询会在最后一刻运行,以尽可能提高效率-称为延迟加载-在第一个示例中,您的
Single()
调用会强制数据提供程序比您希望的更慢

当您调用
Single()
时,您需要一个完整的
学生
记录-所有学生记录列表中的第一个记录,因此必须运行查询(
从SchoolId=1的学校获取SchoolId,SchoolName,…)才能获取该数据。然后调用
Count()
,除了只选择
Count
之外,重放查询

相反,在第二个示例中,仅在调用
Where()
之后才调用
Count()
Where()
不会强制执行查询,因为您尚未访问任何数据,因此数据提供程序只能在计算
COUNT()
后智能地在数据库上播放
GET COUNT
-类型的查询


如何判断LINQ方法是否会“播放”您的查询?我记得,如果它返回
IQueryable
,它将不会播放您的查询,其他任何内容都会播放。

这都与延迟加载有关,但其效果是双重的:

  • context.schools.Where(s=>s.ID==1).Single()
    将返回未加载任何学生的学校实体(惰性加载第1部分)。但是,
  • school.students.Count()
    必须为所有学生点击数据库,因为
    .students
    部分-因为他们没有在第一行加载,所以他们都将被加载(因为您隐式要求-延迟加载部分2),然后
    Count()
    触发

  • 要减少调用,请按照您的建议执行:
    intcnt=context.students.Where(s=>s.schoolID==1.Count()将导致2个db调用,或者像扩展方法那样创建分组结果。

    单一接受IEnumerable或IQueryable?@ScottChamberlain如果您是这样要求的,它将返回IQueryable。
    注意:不查询学校实体不是一个选项,因为我正在使用它的一些字段。
    -查询学校并在两个不同的查询中计数您不是有意义的是,如果是计数,那么将
    var
    更改为int,就像
    var school
    中一样,因为您可以看到它不是计数,而是整个行/实体。有时最简单的方法是,包括您要编写的SQL,并将其转换为linq。还有一些人混淆了懒惰加载的实际含义,我建议你仔细阅读,因为我对这里的其他理解有着复杂的感受。