如何更好地利用 linq to sql 来优化过滤和排序数据?
How to leverage linq to sql better to optimize filtering and sorting data?
我有这段代码,我试图对病原体中报告最多的前五种血清型进行排序。假设有 800 多种血清型可能被报告。我从一个 ObjectQuery
开始,它包含该给定病原体的所有报告。我现在需要计算按每个血清型分组的报告数量,然后拉回前 5 名。我现在是这样写的:
Dictionary<string, int> unsorted = new Dictionary<string, int>();
//'serotypes' is an objectquery of 800+ serotypes
foreach (LookupSerotype serotype in serotypes)
{
var count = Reports.Count(r => r.serotypeId == serotype.serotypeId);
unsorted.Add(serotype.serotypeName, count);
}
// convert to list in memory in order to sort the data
var sorted = unsorted.ToList();
sorted.Sort(delegate(KeyValuePair<string, int> first, KeyValuePair<string, int> next)
{
return first.Value.CompareTo(next.Value);
});
// reverse because the largest were sorted to the bottom
sorted.Reverse();
我可以将其中的大部分(如果不是全部)转换为更多 linq to sql 以便在查询数据库时完成这些计算吗?或者是否有 quicker/better 完全提取此信息的方法?
特别是开头的第一个 foreach 循环花费的时间最长,我可以求助于
如果您想使用 LINQ 执行此操作,这应该可以让您关闭:
var topFive = serotypes.GroupBy(s => s.serotypeName)
.Select(s => new
{
SeroTypeName = s.serotypeName,
Total = s.Count()
}
.OrderByDescending()
.Take(5)
.ToList();
此外,如果您想通过查询在服务器上完成一些工作,您可以使用此 SQL:
Select Top 5 serotype.serotypeName, Count(*) as Total
from serotype
group by serotype.serotypeName
order by Total Desc
如果 serotypes
和 Reports
是 EF IQueryable
s,并且假设 serotype.serotypeId
是 PK(唯一),那么您可以使用基于 group join 像这样:
var query =
(from st in serotypes
join r in Reports on st.serotypeId equals r.serotypeId into stReports
order by st.serotypeName descending
select new { st.serotypeName, reportCount = stReports.Count() }
).Take(5);
var result = query
.AsEnumerable() // switch to LINQ to Objects context
.Select(e => new KeyValuePair<string, int>(e.serotypeName, e.reportCount))
.ToList();
唯一棘手的部分是需要在最终投影之前切换到 LINQ to Objects 上下文,因为 EF 不支持投影 (select
) 到 class/struct w/o 无参数构造函数.
我有这段代码,我试图对病原体中报告最多的前五种血清型进行排序。假设有 800 多种血清型可能被报告。我从一个 ObjectQuery
开始,它包含该给定病原体的所有报告。我现在需要计算按每个血清型分组的报告数量,然后拉回前 5 名。我现在是这样写的:
Dictionary<string, int> unsorted = new Dictionary<string, int>();
//'serotypes' is an objectquery of 800+ serotypes
foreach (LookupSerotype serotype in serotypes)
{
var count = Reports.Count(r => r.serotypeId == serotype.serotypeId);
unsorted.Add(serotype.serotypeName, count);
}
// convert to list in memory in order to sort the data
var sorted = unsorted.ToList();
sorted.Sort(delegate(KeyValuePair<string, int> first, KeyValuePair<string, int> next)
{
return first.Value.CompareTo(next.Value);
});
// reverse because the largest were sorted to the bottom
sorted.Reverse();
我可以将其中的大部分(如果不是全部)转换为更多 linq to sql 以便在查询数据库时完成这些计算吗?或者是否有 quicker/better 完全提取此信息的方法?
特别是开头的第一个 foreach 循环花费的时间最长,我可以求助于
如果您想使用 LINQ 执行此操作,这应该可以让您关闭:
var topFive = serotypes.GroupBy(s => s.serotypeName)
.Select(s => new
{
SeroTypeName = s.serotypeName,
Total = s.Count()
}
.OrderByDescending()
.Take(5)
.ToList();
此外,如果您想通过查询在服务器上完成一些工作,您可以使用此 SQL:
Select Top 5 serotype.serotypeName, Count(*) as Total
from serotype
group by serotype.serotypeName
order by Total Desc
如果 serotypes
和 Reports
是 EF IQueryable
s,并且假设 serotype.serotypeId
是 PK(唯一),那么您可以使用基于 group join 像这样:
var query =
(from st in serotypes
join r in Reports on st.serotypeId equals r.serotypeId into stReports
order by st.serotypeName descending
select new { st.serotypeName, reportCount = stReports.Count() }
).Take(5);
var result = query
.AsEnumerable() // switch to LINQ to Objects context
.Select(e => new KeyValuePair<string, int>(e.serotypeName, e.reportCount))
.ToList();
唯一棘手的部分是需要在最终投影之前切换到 LINQ to Objects 上下文,因为 EF 不支持投影 (select
) 到 class/struct w/o 无参数构造函数.