[英]Modify linq query at runtime
問題陳述
假設我有一個搜索人名的查詢:
var result = (from person in container.people select person)
.Where(p => p.Name.Contains(some_criterion)
這將被轉換為包含以下like子句的SQL查詢:
WHERE NAME LIKE '%some_criterion%'
這有一些性能影響,因為數據庫無法有效地使用名稱列上的索引(索引掃描與索引搜索,如果我沒有記錯)。
為了解決這個問題,我可以決定只使用StartsWith(),使用like子句生成查詢,如:
WHERE NAME LIKE 'some_criterion%'
這使SQL服務器能夠以某些功能為代價使用索引查找和交付性能。
我希望能夠為用戶提供一個選擇:默認行為使用StartsWith,但是如果用戶希望使用Contains()進行搜索的“增加的靈活性”,那么應該使用。
我試過了什么
我認為這是微不足道的,並繼續在字符串上實現了一個擴展方法。 但是當然,LINQ不接受這個並拋出異常。
現在,我當然可以使用if或switch語句並為每個案例創建一個查詢,但我更傾向於在“更高級別”或更一般地解決這個問題。 簡而言之:由於現實應用程序的復雜性,使用if語句來區分用例是不可行的。 這會導致很多重復和混亂。 我真的希望能夠以某種方式封裝變化的行為(Contains,StartsWith,EndsWith)。
題
我應該在哪里看,或者我應該尋找什么? 這是與IQueryables的可組合性的案例嗎? 我很困惑!
使用if語句怎么樣,而不是過度復雜化?
var query = from person in container.people
select person;
if (userWantsStartsWith)
{
query = from p in query
where p.Name.Contains(some_criterion)
select p;
}
else
{
query = from p in query
where p.Name.StartsWith(some_criterion)
select p;
}
更新
如果你真的需要更復雜的東西,試試看LinqKit 。 它允許您執行以下操作。
var stringFunction = Lambda.Expression((string s1, string s2) => s1.Contains(s2));
if (userWantsStartsWith)
{
stringFunction = Lambda.Expression((string s1, string s2) => s1.StartsWith(s2));
}
var query = from p in container.people.AsExpandable()
where stringFunction.Invoke(p.Name, some_criterion)
select p;
我相信這符合你的要求
我真的希望能夠以某種方式封裝變化的行為(Contains,StartsWith,EndsWith)。
您可以在枚舉之前動態更改查詢。
var query = container.people.AsQueryable();
if (contains)
{
query = query.Where(p => p.Name.Contains(filter));
}
else
{
query = query.Where(p => p.Name.StartsWith(filter));
}
嘗試dis:
var result = (from person in container.people select person)
.Where(p => some_bool_variable ? p.Name.Contains(some_criterium) : p.Name.StartsWith(some_criterium));
現實生活中的查詢非常龐大,並與其他幾個人聯合起來。 就像我的問題所說的那樣,這不是我正在尋找的解決方案
Sinse你的查詢是巨大的:你不能只定義處理所有內容的存儲過程並使用特定於查詢參數調用它(可能是由main調用的幾個存儲過程,例如,按名稱搜索em,另一個 - 按Age,有不同的排序順序等以保持代碼清晰)?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.