zoukankan      html  css  js  c++  java
  • 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)....

    @陈卧龙的博客

  • 相关阅读:
    一起学编程(2--认识世界)
    在CentOS 6 中安装 Apache,Mysql, PHP
    JavaScript的代码库
    http get请求获取server返回的应答数据
    Effective C++ 45-48
    通过telent、php深入了解http协议
    UVA 10069 Distinct Subsequences(DP)
    Linux局域网搭建
    iTextSharp之pdfRead(两个文件文本内容的比较,指定页数的pdf截取,水印的添加)
    c#操作pdf文件系列之创建文件
  • 原文地址:https://www.cnblogs.com/chenwolong/p/LinqWhere.html
Copyright © 2011-2022 走看看