c# - 在 foreach/for 中构建 where 子句的延迟查询

标签 c# linq entity-framework entity-framework-4

在解决一个错误时,我遇到了这个问题。这似乎是由于延迟执行,查询正在使用 variable 关键字的最后一个值。解决此问题的推荐模式是什么。

var query = from c in dbContext.Cars
            select c;

var keywords = new string[] { "Clean", "Car" };

foreach (var keyword in keywords)
{
    query = query.Where(c => c.Name.Contains(keyword));
}

var cars = query.ToList();

查询结果如下(注意两个参数的值都是“Car”)

exec sp_executesql N'SELECT 
[Extent1].[CarID] AS [MID], 
[Extent1].[Name] AS [Name], 
FROM [dbo].[Cars] AS [Extent1]
WHERE ([Extent1].[Name] LIKE @p__linq__0 ESCAPE N''~'') AND ([Extent1].[Name] LIKE @p__linq__1 ESCAPE N''~'')
',N'@p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000)',@p__linq__0=N'%Car%',@p__linq__1=N'%Car%'

在 LINQPad 中调试也显示相同的查询

DECLARE p__linq__0 NVarChar(1) = '%Car%'
DECLARE p__linq__1 NVarChar(1) = '%Car%'

SELECT 
[Extent1].[CarID] AS [MID], 
[Extent1].[Name] AS [Name], 
FROM [dbo].[Cars] AS [Extent1]
WHERE ([Extent1].[Name] LIKE @p__linq__0 ESCAPE N'~') AND ([Extent1].[Name] LIKE @p__linq__1 ESCAPE N'~')

最佳答案

这是由于在匿名函数中捕获变量的方式。改变这个:

foreach (var keyword in keywords)
{
    query = query.Where(c => c.Name.Contains(keyword));
}

为此:

foreach (var keyword in keywords)
{
    var copy = keyword;
    query = query.Where(c => c.Name.Contains(copy));
}

它应该可以工作。参见 Eric Lippert's blog post更多细节。 C# 5 的行为正在发生变化,因此此时您无需担心。

但是请注意,您也可以尝试让 LINQ 为您执行此操作:

var query = dbContext.Cars.Where(c => keywords.All(key => c.Name.Contains(key));

我很确定这适用于 Any(有效的“OR”),但我不确定它是否适用于 All。尝试一下...

关于c# - 在 foreach/for 中构建 where 子句的延迟查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10235252/

相关文章:

c# - 为 ClassList 创建多个输入

c# - 使用带有谓词的 linq 无法识别表达式节点 ArrayIndex

c# - 为重复行的特定实例解析定界数据

entity-framework - 修改 Entity Framework 迁移是否安全,以便以不同的方式执行而不是删除并重新创建索引?

c# - Entity Framework 更新错误

c# - Fluent NHibernate - ProjectionList - ICriteria 返回空值

c# - 数据对象属性的最佳实践 : IEnumerable vs Array

c# - 使用 linq 对子列表中具有条件的元素进行计数

c# - 在 LINQ 中转换 OrderBy Case 语句

c# - 有没有办法在事先不知道对象结构的情况下从 JSON 组合匿名类型对象?