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)....

@陈卧龙的博客

posted @ 2017-08-24 15:03  天才卧龙  阅读(3650)  评论(3编辑  收藏  举报