我在很長一段時間裏只有最奇怪的調試體驗。承認這有點尷尬,但它讓我相信當添加一個額外的Where子句時,我的Linq查詢會產生更多結果。爲什麼我的Linq Where子句產生更多結果而不是更少?
我知道這是不可能的,所以我重構我得罪功能加上屬於它進入這個單元測試:
[Test]
public void LoadUserBySearchString()
{
//Setup
var AllUsers = new List<User>
{
new User
{
FirstName = "Luke",
LastName = "Skywalker",
Email = "[email protected]"
},
new User
{
FirstName = "Leia",
LastName = "Skywalker",
Email = "[email protected]"
}
};
//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函數在我手動測試(真正的數據庫用戶)時效果很好。它僅在運行單元測試時顯示這種奇怪的行爲。
我想我只是需要一些睡眠(或甚至延長假期)。如果有人能幫我解釋一下,我可以不再質疑我的理智並回去工作。
感謝,
阿德里安
編輯(澄清的幾個回答,我走這麼遠):我知道這看起來是或條款,但unfortuantely它不是那麼簡單。 LoadUserBySearchString將搜索字符串分割成多個字符串,併爲每個字符串附加一個Where子句。 「天行者」匹配盧克和萊亞,但「公主」只匹配萊亞。
這是搜索字符串「公主」 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>}
這是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子句。
非常感謝!你做了我的一天:-) – 2009-05-06 16:48:19
+1,使用局部變量通常有助於解決關閉問題。進一步閱讀關於在LINQ中使用閉包的方法:http://diditwith.net/2007/09/25/LINQClosuresMayBeHazardousToYourHealth.aspx – Lucas 2009-05-06 17:52:50