2009-12-17 118 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通常可以通过使用访问者模式可以简化,但我省略了,所以你可以更清楚地看到,有许多工作要做的工作。