gpt4 book ai didi

c# - 为什么我的 Linq Where 子句产生更多而不是更少的结果?

转载 作者:行者123 更新时间:2023-11-30 20:14:09 24 4
gpt4 key购买 nike

我刚刚经历了很长一段时间以来最奇怪的调试经历。承认有点尴尬,但它让我相信我的 Linq 查询在添加额外的 Where 子句时会产生更多结果。

我知道这是不可能的,所以我重构了我的违规功能以及属于它的单元测试:

[Test]
public void LoadUserBySearchString()
{
//Setup
var AllUsers = new List<User>
{
new User
{
FirstName = "Luke",
LastName = "Skywalker",
Email = "luke@jedinet.org"
},
new User
{
FirstName = "Leia",
LastName = "Skywalker",
Email = "faeryprincess@winxmail.com"
}
};


//Execution
List<User> SearchResults = LoadUserBySearchString("princess", AllUsers.AsQueryable());
List<User> SearchResults2 = LoadUserBySearchString("princess Skywalker", AllUsers.AsQueryable());

//Assertion
Assert.AreEqual(1, SearchResults.Count); //test passed!
Assert.AreEqual(1, SearchResults2.Count); //test failed! got 2 instead of 1 User???
}


//search CustID, fname, lname, email for substring(s)
public List<User> LoadUserBySearchString(string SearchString, IQueryable<User> AllUsers)
{
IQueryable<User> Result = AllUsers;
//split into substrings and apply each substring as additional search criterium
foreach (string SubString in Regex.Split(SearchString, " "))
{
int SubStringAsInteger = -1;
if (SubString.IsInteger())
{
SubStringAsInteger = Convert.ToInt32(SubString);
}

if (SubString != null && SubString.Length > 0)
{
Result = Result.Where(c => (c.FirstName.Contains(SubString)
|| c.LastName.Contains(SubString)
|| c.Email.Contains(SubString)
|| (c.ID == SubStringAsInteger)
));
}
}
return Result.ToList();
}

我已经调试了 LoadUserBySearchString 函数并断言对该函数的第二次调用实际上生成了一个带有两个 where 子句而不是一个的 linq 查询。因此,附加的 where 子句似乎增加了结果的数量。

更奇怪的是,当我手动测试 LoadUserBySearchString 函数(使用数据库中的真实用户)时,它工作得很好。它只在运行单元测试时显示这种奇怪的行为。

我想我只是需要睡一觉(甚至是长假)。如果有人可以帮助我阐明这一点,我可以停止质疑我的理智并回去工作。

谢谢,

阿德里安

编辑(澄清我到目前为止所做的几个回复):我知道它看起来像是 or 子句,但不幸的是它并没有那么简单。 LoadUserBySearchString 将搜索字符串拆分为多个字符串,并为每个字符串附加一个 Where 子句。 “Skywalker”同时匹配 luke 和 Leia,但“princess”仅匹配 Leia。

这是搜索字符串“princess”的 Linq 查询:

+       Result  {System.Collections.Generic.List`1[TestProject.Models.User].Where(c => (((c.FirstName.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString) || c.LastName.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString)) || c.Email.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString)) || (c.ID = value(TestProject.Controllers.SearchController+<>c__DisplayClass3).SubStringAsInteger)))}  System.Linq.IQueryable<TestProject.Models.User> {System.Linq.EnumerableQuery<TestProject.Models.User>}

这是搜索字符串“princess Skywalker”的 Linq 子句

+       Result  {System.Collections.Generic.List`1[TestProject.Models.User].Where(c => (((c.FirstName.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString) || c.LastName.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString)) || c.Email.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString)) || (c.ID = value(TestProject.Controllers.SearchController+<>c__DisplayClass3).SubStringAsInteger))).Where(c => (((c.FirstName.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString) || c.LastName.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString)) || c.Email.Contains(value(TestProject.Controllers.SearchController+<>c__DisplayClass1).SubString)) || (c.ID = value(TestProject.Controllers.SearchController+<>c__DisplayClass3).SubStringAsInteger)))}    System.Linq.IQueryable<TestProject.Models.User> {System.Linq.EnumerableQuery<TestProject.Models.User>}

同上,只是多了一个 where 子句。

最佳答案

这是一个不错的小问题。

发生的事情是,由于匿名方法和延迟执行,您实际上并没有过滤“公主”。相反,您正在构建一个过滤器,该过滤器将过滤 subString 变量的内容。

但是,您随后更改了这个变量,并构建了另一个过滤器,它再次使用相同的变量。

基本上,这是您要执行的简短形式:

Where(...contains(SubString)).Where(...contains(SubString))

因此,您实际上只过滤了最后一个单词,它存在于两者中,只是因为在实际应用这些过滤器时,只剩下一个 SubString 值,即最后一个。

如果您更改代码以便捕获循环范围内的 SubString 变量,它将起作用:

if (SubString != null && SubString.Length > 0)
{
String captured = SubString;
Int32 capturedId = SubStringAsInteger;
Result = Result.Where(c => (c.FirstName.Contains(captured)
|| c.LastName.Contains(captured)
|| c.Email.Contains(captured)
|| (c.ID == capturedId)
));
}

关于c# - 为什么我的 Linq Where 子句产生更多而不是更少的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/830465/

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