LINQ 如何動態創建 Where 子查詢


還是那句話,十年河東,十年河西,莫欺少年窮!

學無止境,精益求精...

今天探討下如何構造動態的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;

        }
View Code

需要指出的是:

Expression.Or(con, condition);  邏輯或運算
Expression.And(con, condition); 邏輯與運算

分析如下:

生成的LINQ子查詢類似於:c=>c.Tags.Contains(s) || c=>c.Alias.Contains(Alias)....

@陳卧龍的博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM