2009-12-17 57 views
1

我已經想出瞭如何使用LINQ做sql條件查詢,我也想出瞭如何OR where子句。不幸的是,我無法弄清楚如何同時做到這一點。我可以做一個有條件的where子句是這樣的:有條件的地方或條件linqtosql

var ResultsFromProfiles = from AllPeeps in SearchDC.aspnet_Users 
          select AllPeeps; 


if (SearchFirstNameBox.Checked) 
{ 
    ResultsFromProfiles = ResultsFromProfiles.Where(p => p.tblUserProfile.FirstName.Contains(SearchTerm)); 
} 

if (SearchLastNameBox.Checked) 
{ 
    ResultsFromProfiles = ResultsFromProfiles.Where(p => p.tblUserProfile.LastName.Contains(SearchTerm)); 
} 

這將讓我在哪裏,名字和姓氏包含搜索項目的任何文件。

或者我可以這樣做:

var ResultsFromProfiles = from p in SearchDC.aspnet_Users 
          where p.tblUserProfile.LastName.Contains(SearchTerm) || 
           p.tblUserProfile.FirstName.Contains(SearchTerm) 
          select p; 

這將讓我在那裏的第一個名字或姓氏包含搜索詞的任何配置文件。

我有一堆複選框,用戶可以在其中指定他們想要搜索的搜索字詞,所以我希望能夠構建一個有條件添加它們的查詢,如上面的第一個代碼片段所示,但將它們添加爲OR,以便它們像第二個片段一樣工作。這樣它將搜索指定字段中任何位置的任何匹配項。

任何提示?

回答

4

是的,使用PredicateBuilder。它可以讓你用And或Or語義構建動態查詢。它是免費和穩定的 - 我在各地都使用它。

+0

OMG我不知道那個predicateBuilder – Matias 2009-12-17 02:16:37

+0

哦,看起來不錯。特別是與其他建議相比(請參閱下面的條目) – 2009-12-17 02:21:32

+0

輝煌,這正是我所需要的,非常簡單/優雅。 謝謝 – Adam 2009-12-17 20:33:26

0

這是一個建議。

我還沒有試過編譯並運行它,LinqToSQL是充滿驚喜的,所以不能保證:-)要做到這一點

var ResultsFromProfiles = from AllPeeps in SearchDC.aspnet_Users select AllPeeps; 

IEnumerable<AspNet_User> total = new AspNew_User[0]; 

if (SearchFirstNameBox.Checked) 
{  
    total = total.Concat(ResultsFromProfiles.Where(p => p.tblUserProfile.FirstName.Contains(SearchTerm));} 
} 

if (SearchLastNameBox.Checked) 
{ 
    total = total.Concat(ResultsFromProfiles.Where(p => p.tblUserProfile.LastName.Contains(SearchTerm)); 
} 

total = total.Distinct(); 
1

一種方法是操縱LINQ表達式樹爲您的查詢。在你的情況下,你需要建立一個lambda表達式並將其替換爲Where的呼叫。下面是一個基於列表的工作示例,但無論查詢提供程序如何,操作表達式樹的代碼都是相同的。

List<User> Users = new List<User>(); 
Users.Add(new User() { FirstName = "John", LastName = "Smith" }); 
Users.Add(new User() { FirstName = "Jane", LastName = "Smith" }); 


string Query = "John"; 

var Queryable = Users.AsQueryable(); 

var Results = (from u in Queryable 
       select u); 

//initial method call... the lambda u => false is a place-holder that is about to be replaced 
MethodCallExpression WhereExpression = (MethodCallExpression)Results.Where(u => false).Expression; 

//define search options 
Expression<Func<User, string, bool>> FilterLastName = (u, query) => u.LastName.Contains(query); 
Expression<Func<User, string, bool>> FilterFirstName = (u, query) => u.FirstName.Contains(query); 

//build a lambda based on selected search options... tie the u parameter to UserParameter and the query parameter to our Query constant 
ParameterExpression UserParameter = Expression.Parameter(typeof(User), "u"); 
Expression Predicate = Expression.Constant(false); //for simplicity, since we're or-ing, we'll start off with false || ... 

//if (condition for filtering by last name) 
{ 
    Predicate = Expression.Or(Predicate, Expression.Invoke(FilterLastName, UserParameter, Expression.Constant(Query))); 
} 

//if (condition for filtering by first name) 
{ 
    Predicate = Expression.Or(Predicate, Expression.Invoke(FilterFirstName, UserParameter, Expression.Constant(Query))); 
} 

//final method call... lambda u => false is the second parameter, and is replaced with a new lambda based on the predicate we just constructed 
WhereExpression = Expression.Call(WhereExpression.Object, WhereExpression.Method, WhereExpression.Arguments[0], Expression.Lambda(Predicate, UserParameter)); 

//get a new IQueryable for our new expression 
Results = Results.Provider.CreateQuery<User>(WhereExpression); 

//enumerate results as usual 
foreach (User u in Results) 
{ 
    Console.WriteLine("{0} {1}", u.FirstName, u.LastName); 
} 

Working with expression trees通常可以通過使用訪問者模式可以簡化,但我省略了,所以你可以更清楚地看到,有許多工作要做的工作。