還是那句話,十年河東,十年河西,莫欺少年窮!
學無止境,精益求精...
今天探討下如何構造動態的LINQ子查詢
LINQ,相信大家都寫過,很簡單,下面以一個基本的范例說明下:
namespace ConsoleMe { class Program { static List<Person> persons1 = new List<Person>(); static void Main(string[] args) { persons1.Add(new Person("張三", "男", 20, 1500)); persons1.Add(new Person("王成", "男", 32, 3200)); persons1.Add(new Person("李麗", "女", 19, 1700)); persons1.Add(new Person("何英", "女", 35, 3600)); persons1.Add(new Person("何大鳥", "男", 18, 1600)); //LINQ 子查詢 //查詢姓 張、李、王 的人 var Query = from P in persons1 where P.Name.Contains("張") || P.Name.Contains("李") || P.Name.Contains("王") select new PersonModel { Name = P.Name, Sex = P.Sex, Age = P.Age, Money = P.Money }; var list = new List<PersonModel>(); list = Query.ToList(); // } } public class Person { public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } public int Money { get; set; } public Person(string name, string sex, int age, int money) { Name = name; Age = age; Sex = sex; Money = money; } } public class PersonModel { public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } public int Money { get; set; } } }
OK,上述的LINQ查詢很簡單
現在需求有所改變:查詢姓 張 李 王 的男人
LINQ 變更如下:
var Query = from P in persons1 where (P.Name.Contains("張") || P.Name.Contains("李") || P.Name.Contains("王"))&&P.Sex=="男" select new PersonModel { Name = P.Name, Sex = P.Sex, Age = P.Age, Money = P.Money };
現在需求二次變更如下:查詢姓 張 李 王 的男人 並且 年齡要大於20歲
LINQ 二次變更如下:
var Query = from P in persons1 where (P.Name.Contains("張") || P.Name.Contains("李") || P.Name.Contains("王"))&&P.Sex=="男"&&P.Age>20 select new PersonModel { Name = P.Name, Sex = P.Sex, Age = P.Age, Money = P.Money };
好了,如果您認為上述構建WHERE子句的方式就是動態構建的話,那么本篇博客就沒有什么意義了!
那么什么樣的方式才是真正的動態構建呢?
OK,咱們進入正題:
在此我提出一個簡單需求如下:
我相信我的需求提出后,你用上述方式就寫不出來了,我的需求如下:
請根據數組中包含的姓氏進行查詢:
數組如下:
string[] xingList = new string[] { "趙", "錢", "孫", "李", "周", "吳", "鄭", "王", "馮", "陳" };
在這里,有人可能會立馬想到:分割數組,然后用十個 || 進行查詢就行了!
我要強調的是:如果數組也是動態的呢?長度不定,包含的姓氏不定呢?
呵呵,想必寫不出來了吧!
還好,LINQ也有自己的一套代碼可以實現(如果LINQ實現不了,那么早就沒人用LINQ了):
時間問題,就不多寫了,直接粘貼代碼了
詳情可參考:http://www.cnblogs.com/blusehuang/archive/2007/07/13/816970.html
完整的方法是:

public BaseResponse<IList<MessageModel>> GetMessageList(string Tags, string Alias, int pageSize, int pageIndex) { BaseResponse<IList<MessageModel>> response = new BaseResponse<IList<MessageModel>>(); var msg = base.unitOfWork.GetRepository<MSG_Message>().dbSet.Where(A=>!A.IsDeleted);// var Query = from M in msg select new MessageModel { CreatedTime = M.CreatedTime, MessageContent = M.MessageContent, MessageID = M.MessageID, MessageTitle = M.MessageTitle, MessageType = M.MessageType, Tags=M.Tags, Alias=M.Alias }; ParameterExpression c = Expression.Parameter(typeof(MessageModel), "c"); Expression condition = Expression.Constant(false); if (!string.IsNullOrEmpty(Tags)) { string[] TagsAry = new string[] { }; TagsAry = Tags.Split(','); foreach (string s in TagsAry) { Expression con = Expression.Call( Expression.Property(c, typeof(MessageModel).GetProperty("Tags")), typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), Expression.Constant(s)); condition = Expression.Or(con, condition); } } if (!string.IsNullOrEmpty(Alias)) { Expression con_Alias = Expression.Call( Expression.Property(c, typeof(MessageModel).GetProperty("Alias")), typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), Expression.Constant(Alias)); condition = Expression.Or(con_Alias, condition); // } Expression<Func<MessageModel, bool>> end = Expression.Lambda<Func<MessageModel, bool>>(condition, new ParameterExpression[] { c }); Query = Query.Where(end); // response.RecordsCount = Query.Count(); // List<MessageModel> AllList = new List<MessageModel>(); List<MessageModel> AllList_R = new List<MessageModel>(); AllList_R = Query.ToList(); AllList = AllList_R.Where(A => A.Alias.Contains(Alias)).ToList();//加載所有Alias的 for (int i = 0; i < AllList_R.Count; i++) { string[] TagsAry = new string[] { }; if (!string.IsNullOrEmpty(AllList_R[i].Tags)) { TagsAry = AllList_R[i].Tags.Split(','); bool bol = true; foreach (var Cm in TagsAry) { if (!Tags.Contains(Cm)) { bol = false; break; } } if (bol) { AllList.Add(AllList_R[i]); } } } AllList = AllList.OrderByDescending(A => A.CreatedTime).ToList(); if (pageIndex > 0 && pageSize > 0) { AllList = AllList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); response.PagesCount = GetPagesCount(pageSize, response.RecordsCount); } response.Data = AllList; return response; }
需要指出的是:
Expression.Or(con, condition); 邏輯或運算
Expression.And(con, condition); 邏輯與運算
分析如下:
生成的LINQ子查詢類似於:c=>c.Tags.Contains(s) || c=>c.Alias.Contains(Alias)....
@陳卧龍的博客