如何在不使用表两次的情况下加速LINQ查询?

时间:2018-05-01 17:59:30

标签: c# entity-framework linq linq-to-sql

所以我在查询中使用了两次表,我不知道另一种方法只使用它一次。这是我的疑问:

var result = (from t1 in (from t1 in db.Students.Where(en => en.Progress == MyEnum.Accepted).GroupBy(en => en.Class).AsEnumerable()
                          join t2 in dbOther.Classes on t1.Key equals t2.Class 
                          select t2)
              join t3 in (db.Students).AsEnumerable() on t1.Class equals t3.Class into t4
              select new
                          {
                              ClassNum = t1.Class,
                              StartDate = t1.StartDate,
                              Weeks = t1.Weeks,
                              Accepted = t4.Where(e => e.Progress == MyEnum.Accepted).Count(),
                              NotAccepted = t4.Where(e => e.Progress < MyEnum.Accepted).Count()
                          }).ToList();

我只需要让学生处于接受状态的课程。然后我想得到整个名单的班级和数量,甚至是不被接受的学生。有一个更好的方法吗?看起来两次从同一个表读取并不是最快的方法。

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

除非你真的在这里简化了查询,否则你真的不需要点击dbOther来查找任何处于接受状态的学生的课程。该信息位于db

var studentCountPerClass = (from s in db.Students
                            group s by s.Class into studentsByClass    
                            where studentsByClass.Any(x => x.Progress == MyEnum.Accepted)
                            select new
                            {
                                ClassNum = studentsByClass.Key,
                                Accepted = studentsByClass.Count(s => s.Progress == MyEnum.Accepted),
                                NotAccepted = studentsByClass.Count(s => s.Progress < MyEnum.Accepted),
                            })
                            .ToList();

var classCodes = studentCountPerClass.Select(x => x.ClassNum).ToList(); 
var classData = (from c in dbOther.Classes
                    where classCodes.Contains(c.Class)
                    select new {
                        c.Class,
                        // Any other data you want about the class
                    })

答案 1 :(得分:1)

首先,从db.Students表中获取有关学生注册的信息:

var stats = db.Students
    .GroupBy(en => en.Class)
    .Select(g => new {
        Class = g.Key
    ,   Accepted = g.Count(en => en.Progress == MyEnum.Accepted)
    ,   NotAccepted = g.Count(en => en.Progress < MyEnum.Accepted)
    })
    .Where(g => g.Accepted != 0)
    .ToList();

接下来,从其他数据库中获取类:

var classIds = stats.Select(en => en.Class).ToList();
var classes = dbOther.Classes.Where(c => classIds.Contains(c.Class)).ToList();

最后,将两者加入到结果中:

var result = (from s in stats
    join c in classes on c.ClassId = s.ClassId
    select new {
        ClassNum = c.Class
    ,   c.StartDate
    ,   c.Weeks
    ,   s.Accepted
    ,   s.NotAccepted
    }).ToList();

答案 2 :(得分:0)

而不是在学生数据库对象上使用“.Enumerable()”,而是使用Querable。 这将创建一个表达式,该表达式在数据库级别进行评估,而不是先获取整个学生表,然后进行比较。

查看详情Returning IEnumerable<T> vs. IQueryable<T>

只是尝试一下,设置探查器并查看Enumerable和Queryable的生成查询。差异将在那里得到说明。

最简单的实体框架展示了这两种方法的执行差异。也是支持这些功能的最简单的ORM。