我目前正在尝试以下操作。
var groups = MileId == null ? test.Groups.Where(x => x.ProjectId == ProjectId)
: test.Groups.Where(x => x.Milestone == MileId &&
x.ProjectId == ProjectId);
但我还需要通过以下方式过滤群组的其他条款:
foreach (var ChartItem in ChartItems)
{
foreach (var StatusItem in ChartItem.ChartStatusItems)
{
foreach (var PriorityItem in StatusItem.ChartPriorityItems)
{
filteredgroups.AddRange(
groups.Where(x => x.Status == StatusItem.StatusID
&& x.Priority == PriorityItem.PriorityID));
}
}
}
这很好并且它可以工作但是添加范围时嵌套的foreach循环非常慢。如果我在循环之前使用groups.toList(),那么该语句很慢并且嵌套循环很快。
我的问题是:
是否可以动态地根据这些StatusIds和PriorityIds从一开始过滤组?怎么样?
Stackoverflow推荐基于我的主题行的表达式树上的一些文章......我需要研究什么?
谢谢
编辑:
所以我现在正在这样做:
foreach (var ChartItem in ChartItems)
{
foreach (var StatusItem in ChartItem.ChartStatusItems)
{
foreach (var PriorityItem in StatusItem.ChartPriorityItems)
{
var groups = MileId == null ? test.Groups.Where(x => x.ProjectId == InspectorProjectId &&
x.Status == StatusItem.StatusID &&
x.Priority == PriorityItem.PriorityID)
: test.Groups.Where(x => x.Milestone == InspectorMileId &&
x.ProjectId == InspectorProjectId &&
x.Status == StatusItem.StatusID &&
x.Priority == PriorityItem.PriorityID);
filteredgroups.AddRange(groups);
}
}
}
这是一个很大的改进,但它仍然会针对每个优先级慢速'测试'服务器。如果我能把它全部过滤掉,那将是理想的。
编辑2:哦,我无法直接访问数据库:(我们通过API访问它。
答案 0 :(得分:4)
所有这些都应该在数据库中发生。只需创建一个连接所有这些表的视图。在交叉和连接数据集时,很难比数据库更快。
答案 1 :(得分:1)
您可以使用Contains
吗?
var filteredgroups =
test.Groups.Where(x =>
(MileId == null || x.Milestone == MileId) // (replaces ?: in original)
&& x.ProjectId == ProjectId
&& ChartItem.ChartStatusItems.Contains(x.Status)
&& StatusItem.ChartPriorityItems.Contains(x.Priority));
(我不确定Linq-to-Sql和Linq-to-Objects将如何与性能进行交互,但至少它简洁......)
答案 2 :(得分:0)
foreach
循环很可能正在执行延迟调用,这很可能在每个foreach
循环中命中数据库。但是您不必使用SelectMany
,只需构建查询:
var statuses = ChartItems
.SelectMany(x => x.ChartStatusItems)
.Select(i => i.StatusId);
var priorities = ChartItems
.SelectMany(x => x.ChartPriorityItems)
.Select(i => i.PriorityId);
var filtered = groups.Where(x => statuses.Contains(x.Status) &&
priorities.Contains(x.Priority))
答案 3 :(得分:0)
也许您可以在.Any()
内拨打.Where()
并完全跳过循环。
test.Groups.Where(x => (MileId == null ||
x.Milestone == MileId) &&
x.ProjectId == ProjectId &&
ChartItems.Any(c => c.ChartStatusItems.Any(s => s.StatusId == x.StatusId &&
s.ChartPriorityItems.Any(p => p.PriorityId == x.PriorityId))));