mvc 多條件查詢時,不想用拼接的方式,搜索了一圈,記錄一下過程,最初採用 如下代碼
- public static class PredicateExtensions
- {
- public static Expression<Func<T, bool>> True<T>() { return f => true; }
- public static Expression<Func<T, bool>> False<T>() { return f => false; }
- public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
- {
- var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
- return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression), expression1.Parameters);
- }
- public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
- {
- var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
- return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters);
- }
- }
- 用如下:
- /// <summary>
- /// 獲取用戶列表 分頁
- /// </summary>
- /// <param name="pageIndex">頁碼</param>
- /// <param name="pageSize">每頁記錄數</param>
- /// <param name="paras">查詢參數</param>
- /// <returns></returns>
- public List<NewUser> GetUserList(int pageIndex, int pageSize, Dictionary<string,string> paras, out int totalcount)
- {
- totalcount=db.LsNewUsers.Count();
- int startRow=(pageIndex-1)*pageSize;
- return db.LsNewUsers.AsNoTracking().Where(<span style="color:#ff0000;">GetExpression(paras).Compile</span>()).OrderBy(u => u.UserId).Skip(startRow).Take(pageSize).ToList();
- }
- /// <summary>
- /// 獲取查詢條件 表達式樹
- /// </summary>
- /// <param name="dicParam">參數列表</param>
- /// <returns></returns>
- public Expression<Func<NewUser, bool>> GetExpression(Dictionary<string,string> dicParam)
- {
- //個人理解,類似 賦給一個初始 條件 1=1 和 and方法一起用; 如果是false方法,類似賦給一個初始條件1!=1,和or方法一起用.
- Expression<Func<NewUser, bool>> searchPredicate = PredicateExtensions.True<NewUser>();
- foreach (string key in dicParam.Keys)
- {
- string condition = string.Empty;
- switch (key.ToLower())
- {
- case "username": //case自己擴展
- condition = dicParam[key];
- searchPredicate = searchPredicate.And(c => c.UserName.IndexOf(condition)>-1);
- break;
- case "sex":
- condition = dicParam[key];
- bool blsex=true;
- bool.TryParse(condition,out blsex);
- searchPredicate = searchPredicate.And(c => c.Sex==blsex);
- break;
- default:
- break;
- }
- }
- return searchPredicate;
- }
重點是這一句:
db.LsNewUsersWhere( condition.Compile()).OrderBy(u => u.UserId).Skip(startRow).Take(pageSize).ToList();
可以通過,但是 會出現 http://bbs.csdn.net/topics/390254489 中出現的問題,查詢時,sql profiler 監視發現是查詢全部表。
於是我去掉 complie方法,發現會出現 The LINQ expression node type 'Invoke' is not supported in LINQ to Entities 的錯誤
網上找了一圈。發現可以使LinqKit.dll 來解決這個entity framework中的這個問題
參考文章:http://www.albahari.com/nutshell/predicatebuilder.aspx
剛開始 百度搜了一個linqkit.dll,雖然方法有,但是錯誤依舊。。抱着試一試的態度,找到了上面文章中的linqkit的地址。下載下來,錯誤消失。
dll 下載地址:http://www.albahari.com/nutshell/LinqKit.zip
相關文章:http://www.albahari.com/nutshell/linqkit.aspx
怕國外的網站不行,自己也上傳了一份,地址:http://download.csdn.net/detail/laokaizzz/7167477
因爲我用的是 ef,所以得使用dll,又因爲是。net 4.0 不是 4.5,不能直接從nuget裏安裝,所以直接引用的dll.
最終代碼
使用如下:
/// <summary>
/// 獲取用戶列表 分頁
/// </summary>
/// <param name="pageIndex">頁碼</param>
/// <param name="pageSize">每頁記錄數</param>
/// <param name="paras">查詢參數</param>
/// <returns></returns>
public List<NewUser> GetUserList(int pageIndex, int pageSize, Dictionary<string,string> paras, out int totalcount)
{
int startRow=(pageIndex-1)*pageSize;
Expression<Func<NewUser, bool>> condition=GetExpression(paras);
totalcount = db.LsNewUsers.AsExpandable().Where(condition).Count();//獲取總數 AsExpandable是linqkit.dll中的方法
return db.LsNewUsers.AsExpandable().Where(condition).OrderBy(u => u.UserId).Skip(startRow).Take(pageSize).ToList();
}
/// <summary>
/// 獲取查詢條件 表達式樹
/// </summary>
/// <param name="dicParam">參數列表</param>
/// <returns></returns>
public Expression<Func<NewUser, bool>> GetExpression(Dictionary<string,string> dicParam)
{
//個人理解,類似 賦給一個初始 條件 1=1 和 and方法一起用; 如果是false方法,類似賦給一個初始條件1!=1,和or方法一起用.
Expression<Func<NewUser, bool>> searchPredicate = PredicateBuilder.True<NewUser>();
foreach (string key in dicParam.Keys)
{
string condition = string.Empty;
switch (key.ToLower())
{
case "username": //case自己擴展
condition = dicParam[key];
searchPredicate = searchPredicate.And(c => c.UserName.IndexOf(condition)>-1);
break;
case "sex":
condition = dicParam[key];
bool blsex=true;
bool.TryParse(condition,out blsex);
searchPredicate = searchPredicate.And(c => c.Sex==blsex);
break;
default:
break;
}
}
return searchPredicate;
}