为什么我的绑定参数都相同(使用Linq)?

Sco*_*ord 5 c# linq binding linq-to-sql

当我运行这段代码时:

string[] words = new string[] { "foo", "bar" };
var results = from row in Assets select row;
foreach (string word in words)
{
    results = results.Where(row => row.Name.Contains(word));
}
Run Code Online (Sandbox Code Playgroud)

我得到这个SQL:

-- Region Parameters
DECLARE @p0 VarChar(5) = '%bar%'
DECLARE @p1 VarChar(5) = '%bar%'
-- EndRegion
SELECT ... FROM [Assets] AS [t0]
WHERE ([t0].[Name] LIKE @p0) AND ([t0].[Name] LIKE @p1)
Run Code Online (Sandbox Code Playgroud)

请注意,@p0@p1都是bar,当我想他们是foobar.

我猜Linq以某种方式绑定对变量word的引用而不是对当前引用的字符串的引用word?避免这个问题的最佳方法是什么?

(另外,如果您对此问题有更好的标题有任何建议,请将其放在评论中.)

请注意,我也尝试使用常规Linq,结果相同(您可以将其粘贴到Linqpad中):

string[] words = new string[] { "f", "a" };
string[] dictionary = new string[] { "foo", "bar", "jack", "splat" };
var results = from row in dictionary select row;
foreach (string word in words)
{
    results = results.Where(row => row.Contains(word));
}
results.Dump();
Run Code Online (Sandbox Code Playgroud)

转储:

bar
jack
splat
Run Code Online (Sandbox Code Playgroud)

Ada*_*son 8

你正在使用所谓的"闭包",这意味着你要定义一个在其体内使用局部变量的匿名函数(你的lambda).具体来说,你正在"关闭"循环变量word.闭包产生的问题是由延迟执行引起的,这意味着lambda的主体在定义时不会运行,而是在调用时运行.

因此,您几乎不想关闭循环变量.由于延迟执行,lambda中变量的值将是执行lambda时的值.对于在循环内声明并在其外部调用的lambdas,这意味着它将始终具有循环中的最后一个值.

要抵消这种情况,请使用循环内声明的局部变量.这将使它捕获该时间点的值,并将新变量传递给创建的每个lambda.像这样:

string[] words = new string[] { "foo", "bar" }; 
var results = from row in Assets select row; 
foreach (string word in words) 
{ 
    string tempWord = word;

    results = results.Where(row => row.Name.Contains(tempWord)); 
} 
Run Code Online (Sandbox Code Playgroud)