2013-12-13 45 views
1

如何動態構建一個linq OR查詢,其中幾列之一可以匹配搜索字符串?這在SQL中並不難。例如:如何動態構建一個linq OR查詢,其中幾列之一可以匹配搜索字符串?

SELECT  ID, Title, Description, Comments, CreatedBy, CreatedOn, UpdatedBy, UpdatedOn 
FROM   Category 
WHERE  (Title LIKE '%Supplier%') 
    OR (Description LIKE '%Supplier%') 

有時我會需要添加OR (Comments LIKE '%Supplier%')或省略OR (Title LIKE '%Supplier%'),這就是爲什麼我要動態地生成它。

我不認爲這是一個重複的問題,因爲潛在的重複不會以可以使用Stackoverflow搜索功能找到的方式被詢問。

回答

0

我最終解決了這個問題,結合了evanmcdonnal和dasblinkenlight的想法。不幸的是,我給他們每個人都贊成,因爲幫助回答了這個問題,我無法給他們每一分。這就是我最終寫的。

private static IQueryable<Db.Category> FilterContains(string searchFor, string excludedBrFields, IQueryable<Db.Category> categories) 
{ 
    if (searchFor.StartsWith("*") && searchFor.EndsWith("*")) 
    { 
     searchFor = searchFor.Substring(1, searchFor.Length - 2); 
    } 
    searchFor = searchFor.ToLower(); 

    var predicate = PredicateBuilder.False<Db.Category>(); 
    if (!excludedBrFields.Contains("Title")) 
    { 
     predicate = predicate.Or(x => x.Title.ToLower().Contains(searchFor)); 
    } 

    if (!excludedBrFields.Contains("Description")) 
    { 
     predicate = predicate.Or(x => x.Description != null && x.Description.ToLower().Contains(searchFor)); 
    } 

    if (!excludedBrFields.Contains("Comments")) 
    { 
     predicate = predicate.Or(x => x.Comments != null && x.Comments.ToLower().Contains(searchFor)); 
    } 
    return categories.Where(predicate.Compile()).AsQueryable(); 
} 
4

你只是使用或運算符就像你在C#中的其他地方。下面的代碼片段應該基本上做你想要的。字符串文字可以改爲局部變量。

MyObjects.Where(x => x.Someprop == "my string" || x.SomeOtherprop == "my string").Select(...) 

爲了您的例子中,你實際上想要的東西更像

Where(x => x.Comments.Contains("Supplier") || x.Description.Contains("Supplier")) 

注意,這些SQL通配符相當於C#方法會;包含,StartsWith和EndsWith。您也可以使用RegEx來匹配更復雜的模式。

+0

我們絕對走在正確的軌道上。但是,有時我需要添加「OR(註釋LIKE'%Supplier%')」或刪除「OR(標題LIKE'%Supplier%')」,這就是爲什麼我要動態構建它的原因。直到運行時,我才知道要查詢哪些列。我如何處理這些案件? – Tarzan

+0

@Tarzan你有一些不同的選項,但我會建議只寫不同版本的查詢,並確定哪一個與典型的if-elseif結構運行。想到的另一個選擇是使用反射,但這比它值得imo更有用。 – evanmcdonnal

+0

我最終解決了這個問題,結合了你和dasblinkenlight的想法。 – Tarzan

-1

這裏是LINQ例如:

public IEnumerable<Items> FindBySupplier(string supplier) 
{ 
return context.Items.Where(i => i.Title.ToLower().Contains(supplier.ToLower()) || i.Description.ToLower().Contains(supplier.ToLower()); 

}

+1

您調用較低的然後傳遞包含以大寫字母開頭的字符串...該代碼將永遠不會工作。 – evanmcdonnal

+0

是的,sry,我的意思是供應商是一個變量,而不是硬編碼的字符串。 – Valin

+0

仍然無法正常工作。如果你正在進行字符串比較,並將其應用於字符串中較低或較高的字符串,則必須將其應用於另一個字符串,否則邏輯不完整。 – evanmcdonnal

1

使用lambda。可能會爲你工作。

context.Category.Where(x=>x.Title.Contains("Supplier") || x.Description.Contains("Supplier")).Select(x=>new {....}); 
2

建設有OR查詢動態就沒有那麼簡單,因爲它是建立與AND查詢。如果您設置爲動態構建查詢,則可以使用Predicate Builder。如果你不介意,可以動態地忽視其條件的部分單查詢,你可以使用下面的查詢:

bool checkTitle = ... 
bool checkDescription = ... 
string likeString = ... 
var res = context.Category 
    .Where(item => 
     (checkTitle && item.Title.Contains(likeString)) 
     || 
     (checkDescription && item.Description.Contains(likeString)) 
    ); 

由於str.Contains("xyz")轉化爲str LIKE '%xyz%',這個查詢將對應於一個SQL查詢是這樣的:

SELECT ID, Title, Description, Comments, CreatedBy, CreatedOn, UpdatedBy, UpdatedOn 
FROM Category 
WHERE (@checkTitle=1 AND Title LIKE '%Supplier%') 
    OR (@checkDescription=1 AND Description LIKE '%Supplier%') 
相關問題