gpt4 book ai didi

c# - Linq 多重 where 查询

转载 作者:可可西里 更新时间:2023-11-01 09:10:19 29 4
gpt4 key购买 nike

我在构建相当繁重的 linq 查询时遇到了问题。基本上我有一种情况,我需要在循环中执行子查询以过滤掉从数据库返回的匹配项的数量。示例代码在下面的循环中:

        foreach (Guid parent in parentAttributes)
{
var subQuery = from sc in db.tSearchIndexes
join a in db.tAttributes on sc.AttributeGUID equals a.GUID
join pc in db.tPeopleIndexes on a.GUID equals pc.AttributeGUID
where a.RelatedGUID == parent && userId == pc.CPSGUID
select sc.CPSGUID;

query = query.Where(x => subQuery.Contains(x.Id));
}

当我随后在查询变量上调用 ToList() 时,似乎只执行了一个子查询,剩下一桶我不需要的数据。然而,这种方法有效:

       IList<Guid> temp = query.Select(x => x.Id).ToList();

foreach (Guid parent in parentAttributes)
{
var subQuery = from sc in db.tSearchIndexes
join a in db.tAttributes on sc.AttributeGUID equals a.GUID
join pc in db.tPeopleIndexes on a.GUID equals pc.AttributeGUID
where a.RelatedGUID == parent && userId == pc.CPSGUID
select sc.CPSGUID;

temp = temp.Intersect(subQuery).ToList();
}

query = query.Where(x => temp.Contains(x.Id));

不幸的是,这种方法很糟糕,因为它会导致对远程数据库进行多次查询,而如果我能让它工作的话,最初的方法只会导致一次命中。有什么想法吗?

最佳答案

我认为您遇到了一种特殊情况,即在用于过滤的 lambda 表达式中捕获循环变量。也称为访问修改后的闭包错误。

试试这个:

   foreach (Guid parentLoop in parentAttributes)
{
var parent = parentLoop;
var subQuery = from sc in db.tSearchIndexes
join a in db.tAttributes on sc.AttributeGUID equals a.GUID
join pc in db.tPeopleIndexes on a.GUID equals pc.AttributeGUID
where a.RelatedGUID == parent && userId == pc.CPSGUID
select sc.CPSGUID;

query = query.Where(x => subQuery.Contains(x.Id));
}

问题是捕获闭包中的 parent 变量(LINQ 语法被转换为),这导致所有 subQueryes 都在同一个父级上运行编号。

编译器会生成一个类来保存委托(delegate)和委托(delegate)访问的局部变量。编译器为每个循环重复使用该类的相同实例;因此,一旦查询执行,所有 Where 都使用相同的 parent Guid 执行,即最后执行。

在循环范围内声明 parent 会导致编译器实质上制作一个具有正确值的变量副本,以进行捕获。

一开始可能有点难以理解,所以如果这是第一次遇到这种情况;我推荐这两篇文章作为背景和详尽的解释:

关于c# - Linq 多重 where 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9673027/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com