如何在不使用 table 两次的情况下加快我的 LINQ 查询?
How can I speed up my LINQ query without using a table twice?
所以我在查询中使用了两次 table,而且我不知道还有什么方法可以只使用它一次。这是我的查询:
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();
我只需要 类 有学生处于接受状态。然后我想得到 类 及其整个花名册的计数,甚至是未被录取的学生。有一个更好的方法吗?似乎从同一个 table 读取两次并不是最快的方法。
感谢您的帮助。
除非您真的要在这里简化查询,否则您真的不需要点击 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
})
不要在学生数据库对象上使用“.Enumerable()”,而是使用 Querable。
这将创建一个表达式,该表达式在数据库级别进行评估,而不是先获取整个学生 table 然后进行比较。
查看这里了解详细信息Returning IEnumerable<T> vs. IQueryable<T>
只是为了尝试,设置探查器并查看为 Enumerable 和 Queryable 生成的查询。差异将在此处说明。
Entity framework 最容易展示,这两种方法在执行上存在差异。也是支持这些功能的最简单的ORM。
首先,从 db.Students
table:
中获取有关学生注册的信息
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();
所以我在查询中使用了两次 table,而且我不知道还有什么方法可以只使用它一次。这是我的查询:
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();
我只需要 类 有学生处于接受状态。然后我想得到 类 及其整个花名册的计数,甚至是未被录取的学生。有一个更好的方法吗?似乎从同一个 table 读取两次并不是最快的方法。
感谢您的帮助。
除非您真的要在这里简化查询,否则您真的不需要点击 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
})
不要在学生数据库对象上使用“.Enumerable()”,而是使用 Querable。 这将创建一个表达式,该表达式在数据库级别进行评估,而不是先获取整个学生 table 然后进行比较。
查看这里了解详细信息Returning IEnumerable<T> vs. IQueryable<T>
只是为了尝试,设置探查器并查看为 Enumerable 和 Queryable 生成的查询。差异将在此处说明。
Entity framework 最容易展示,这两种方法在执行上存在差异。也是支持这些功能的最简单的ORM。
首先,从 db.Students
table:
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();