还是那句话,十年河东,十年河西,莫欺少年穷!

学无止境,精益求精...

今天探讨下如何构造动态的LINQ子查询

LINQ,相信大家都写过,很简单,下面以一个基本的范例说明下:

    namespace ConsoleMe
{
class Program
{
static List<Person> persons1 = new List<Person>();
static void Main(string[] args)
{
persons1.Add(new Person("张三", "男", , ));
persons1.Add(new Person("王成", "男", , ));
persons1.Add(new Person("李丽", "女", , ));
persons1.Add(new Person("何英", "女", , ));
persons1.Add(new Person("何大鸟", "男", , )); //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>
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 = ; 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 > && pageSize > )
{
AllList = AllList.Skip((pageIndex - ) * 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)....

@陈卧龙的博客

LINQ 如何动态创建 Where 子查询的更多相关文章

  1. LINQ之路 7:子查询、创建策略和数据转换

    在前面的系列中,我们已经讨论了LINQ简单查询的大部分特性,了解了LINQ的支持计术和语法形式.至此,我们应该可以创建出大部分相对简单的LINQ查询.在本篇中,除了对前面的知识做个简单的总结,还会介绍 ...

  2. C# linq对分组操作执行子查询

    本主题演示创建查询的两种不同方式,此查询将源数据排序成组,然后分别对每个组执行子查询. 每个示例中的基本方法是使用名为 newGroup 的"接续块"对源元素进行分组,然后针对 n ...

  3. Linq to SQL 语法整理(子查询 & in操作 & join )

    子查询 描述:查询订单数超过5的顾客信息 查询句法: var 子查询 = from c in ctx.Customers where (from o in ctx.Orders group o by ...

  4. LINQ之路 7:子查询、创建策略和数据转换(要点笔记)

    匿名类型 上面我们自己定义了类型TempProjectionItem来存放查询的结果.通过使用匿名类型,我们可以省去这种中间类型的定义,而由编译器来帮我们完成: select item.Origina ...

  5. 用jQuery绑定事件到动态创建的元素上

    jQuery最常用的一个功能就是对DOM的操作,与之相关的比如对事件的绑定和Ajax动态内容加载.当我们绑定事件到Ajax load回来的内容上或其他动态创建的元素上时会发现事件没响应,和你预想的结果 ...

  6. 动态创建Lambda表达式实现高级查询

    需求简介 最近这几天做的东西总算是回归咱的老本行了,给投资管理项目做一个台账的东西,就是类似我们的报表.其 中有一个功能是一个高级查询的需求,在查询条件方面大概有7.8个查询条件.需求就是如果一个条件 ...

  7. Linq to SQL 语法查询(链接查询,子查询 & in操作 & join,分组统计等)

    Linq to SQL 语法查询(链接查询,子查询 & in操作 & join,分组统计等) 子查询 描述:查询订单数超过5的顾客信息 查询句法: var 子查询 = from c i ...

  8. Linq专题之创建Linq查询表达式

    本节我们主要介绍一下如何创建查询集合类型,关系数据库类型,DataSet对象类型和XML类型的数据源的Linq查询表达式. 下面在实例代码ReadyCollectionData()函数创建了准备的数据 ...

  9. Linq To Sql 语法 子查询 & In & Join

    子查询 描述:查询订单数超过5的顾客信息 查询句法: var 子查询 =from cin ctx.Customers                    where                  ...

随机推荐

  1. Openlayer3之空间参考扩展

    Openlayers默认了两种空间参考,一个是EPSG4326,一个是EPSG3857,其它的空间参考需要进行扩展才能使用.所以我们初始化时进行了如下操作: 1.将配置数据库中所有的空间参考读取出来, ...

  2. Installing Language Tool in TexStudio

    This is a recent and more detailed solution for Windows users. Make sure the last version of TeXstud ...

  3. Linux 下修改网卡接口名

    Linux下修改网卡接口名 by:授客 QQ:1033553122 (测试环境:CentOS-6.0-x86_64-bin-DVD1.iso+Vmware) 作用 可以用于解决类似如下Device n ...

  4. AngularJS ui-router刷新子页面路由

    网上有各种刷新子页面路由的方法,但是不知道为什么放到我的页面就不行了,尴尬! 网上的方法有: <a href="#" ui-sref="app.toMenu&quo ...

  5. 【HANA系列】SAP HANA XS的JavaScript API详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS的Java ...

  6. sql server 运维时CPU,内存,操作系统等信息查询(用sql语句)

    我们只要用到数据库,一般会遇到数据库运维方面的事情,需要我们寻找原因,有很多是关乎处理器(CPU).内存(Memory).磁盘(Disk)以及操作系统的,这时我们就需要查询他们的一些设置和内容,下面讲 ...

  7. 万能Makefile,前戏做足项目做起来才顺畅。

    # 获取要编译的源码 SRC :=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) # 编译参数 CC :=g++ STD :=-std=c++ ...

  8. VS 2015连接SQL server数据库方法

    vs新建一个Windows窗口应用程序,界面布局如下: Form1.cs中代码如下: using System; using System.Collections.Generic; using Sys ...

  9. STL set简单用法

    set的常见用法详解 set翻译为集合,是一个内部自动有序并且不含重复元素的容器. 可以用于去掉重复元素,或者元素过大,或者不能散列的情况,set只保留元素本身而不考虑它的个数. 头文件:#inclu ...

  10. Visualbox与CentOS 6.4之间鼠标切换

    按住键盘右边的Alt键,再按一下(右边)ctrl键,这样可以实现鼠标能在主机与虚拟机之间自由切换.