动态LINQ(Lambda表达式)构建
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using NUnit.Framework; namespace ConsoleApplication1
{
/// <summary>
/// 动态Linq
/// </summary>
[TestFixture]
public class LinqTest
{ [Test]
public void Test()
{
#region 动态Linq(动态lambda表达式构建) QueryCondition queryCondition = new QueryCondition(null, "动态测试", new DateTime(, , ), new DateTime(, , ), null, null, , true);
QueryCondition queryCondition2 = new QueryCondition(null, string.Empty, null, null, null, , , false); QueryCondition queryCondition3 = new QueryCondition(null, string.Empty, null, new DateTime(, , ), null, , , true); QueryCondition[] queryConditionLs = new QueryCondition[] { queryCondition, queryCondition2, queryCondition3 };
DynamicLambda dynamicLinq = new DynamicLambda(); List<TestUser> queryLs;
queryLs = dynamicLinq.GetTestData();
Console.WriteLine("原始测试数据有{0}条,如下\n", queryLs.Count);
dynamicLinq.PrintResult(queryLs); Console.WriteLine("---------------查询分隔符------------------\n"); //queryLs = dynamicLinq.GetDataByGeneralQuery(queryConditionLs[0]);
queryLs = dynamicLinq.GetDataByDynamicQuery(queryConditionLs[]);
Console.WriteLine("满足查询结果的数据有{0}条,如下\n", queryLs.Count);
dynamicLinq.PrintResult(queryLs); #endregion Console.ReadLine();
} /// <summary>
/// 动态Lambda表达式类
/// </summary>
public class DynamicLambda
{
public Dictionary<string, string> queryDict = new Dictionary<string, string>();
public OrderEntry[] orderEntries; public DynamicLambda()
{
InitDynamicQueryMapping();
orderEntries = new OrderEntry[] {
new OrderEntry(){OrderStr="Id",OrderType=typeof(int)},
new OrderEntry(){OrderStr="Name",OrderType=typeof(string)},
new OrderEntry(){OrderStr="Birth",OrderType=typeof(string)},
new OrderEntry(){OrderStr="IsStudent",OrderType=typeof(string)},
new OrderEntry(){OrderStr="Cellphone",OrderType=typeof(string)},
new OrderEntry(){OrderStr="Email",OrderType=typeof(string)},
new OrderEntry(){OrderStr="Score",OrderType=typeof(int)}
};
} /*在一般的业务环境中我们常常会遇到动态查询的情况,对于以前纯T-SQL情况下我们一般是采用根据相应条件动态拼接相应的where条件上去达到相应效果
如今在这个LINQ横行的年代,怎么能利用LINQ完成动态查询呢
*/ #region 一般的解决方案 //如果要根据对应的Linq的方式怎么完成
public List<TestUser> GetDataByGeneralQuery(QueryCondition queryCondition)
{
//此处一般会从数据库或者其他地方获取到业务所用到的数据源
List<TestUser> sourceLs = GetTestData(); /*根据不同情况添加不同查询条件,但是我们都摘掉平时开发中需求是不断变化的,怎么能更好的应对PM各种扭曲的要求尔不必一次一次的添加各种if条件呢
万一有一天,PM要求你将某些条件合并例如名字和ID变为OR的关系怎么办,如果需要利用LINQ进行动态的排序怎么办,或者如果过滤的名字是一个
不定的字符串数组怎么办,这些都是我们经常会遇到的,我们不能因为每次这样的改动而去修改这里的东西, 而且有的时候我们知道在Where(n=>n.?==?)
但是编译器是不知道的,这是我们就要用到动态lambda表达式(动态linq的方式)
*/
if (queryCondition.QueryId.HasValue)
sourceLs = sourceLs.Where(n => n.Id == queryCondition.QueryId).ToList<TestUser>();
if (!string.IsNullOrEmpty(queryCondition.QueryName))
sourceLs = sourceLs.Where(n => n.Name.ToLower().Contains(queryCondition.QueryName.ToLower())).ToList<TestUser>();
if (queryCondition.QueryStartTime.HasValue)
sourceLs = sourceLs.Where(n => n.Birth >= queryCondition.QueryStartTime.Value).ToList<TestUser>();
if (queryCondition.QueryEndTime.HasValue)
sourceLs = sourceLs.Where(n => n.Birth < queryCondition.QueryEndTime.Value).ToList<TestUser>();
if (queryCondition.QueryBoolean != null)
sourceLs = sourceLs.Where(n => n.IsStudent = queryCondition.QueryBoolean.Value).ToList<TestUser>();
if (queryCondition.QueryScore.HasValue)
sourceLs = sourceLs.Where(n => n.Score == queryCondition.QueryScore.Value).ToList<TestUser>(); switch (queryCondition.OrderField)
{
case :
{
if (queryCondition.IsDesc)
sourceLs = sourceLs.OrderByDescending(n => n.Id).ToList<TestUser>();
else
sourceLs = sourceLs.OrderBy(n => n.Id).ToList<TestUser>();
}; break;
case :
{
if (queryCondition.IsDesc)
sourceLs = sourceLs.OrderByDescending(n => n.Name).ToList<TestUser>();
else
sourceLs = sourceLs.OrderBy(n => n.Name).ToList<TestUser>();
}; break;
case :
{
if (queryCondition.IsDesc)
sourceLs = sourceLs.OrderByDescending(n => n.Birth).ToList<TestUser>();
else
sourceLs = sourceLs.OrderBy(n => n.Birth).ToList<TestUser>();
}; break;
case :
{
if (queryCondition.IsDesc)
sourceLs = sourceLs.OrderByDescending(n => n.IsStudent).ToList<TestUser>();
else
sourceLs = sourceLs.OrderBy(n => n.IsStudent).ToList<TestUser>();
}; break;
case :
{
if (queryCondition.IsDesc)
sourceLs = sourceLs.OrderByDescending(n => n.Cellphone).ToList<TestUser>();
else
sourceLs = sourceLs.OrderBy(n => n.Cellphone).ToList<TestUser>();
}; break;
case :
{
if (queryCondition.IsDesc)
sourceLs = sourceLs.OrderByDescending(n => n.Email).ToList<TestUser>();
else
sourceLs = sourceLs.OrderBy(n => n.Email).ToList<TestUser>();
}; break;
case :
{
if (queryCondition.IsDesc)
sourceLs = sourceLs.OrderByDescending(n => n.Score).ToList<TestUser>();
else
sourceLs = sourceLs.OrderBy(n => n.Score).ToList<TestUser>();
}; break;
default:
break;
} return sourceLs;
} #endregion #region 动态构建Lambda表达式-动态Expression树 public List<TestUser> GetDataByDynamicQuery(QueryCondition queryCondition)
{
IQueryable<TestUser> sourceLs = GetTestData().AsQueryable<TestUser>();
string[] orderParams = new string[] { "OrderField", "IsDesc" }; Expression filter;
Expression totalExpr = Expression.Constant(true); ParameterExpression param = Expression.Parameter(typeof(TestUser), "n");
Type queryConditionType = queryCondition.GetType();
foreach (PropertyInfo item in queryConditionType.GetProperties())
{
//反射找出所有查询条件的属性值,如果该查询条件值为空或者null不添加动态lambda表达式
string propertyName = item.Name;
var propertyVal = item.GetValue(queryCondition, null); if (!orderParams.Contains(propertyName) && propertyVal != null && propertyVal.ToString() != string.Empty)
{
//n.property
Expression left = Expression.Property(param, typeof(TestUser).GetProperty(queryDict[propertyName]));
//等式右边的值
Expression right = Expression.Constant(propertyVal);
//此处如果有特殊的判断可以自行修改例如要是Contain的,要是时间大于小于的这种判断, 这里也可以用类似InitDynamicQueryMapping方法进行表驱动维护 if (propertyName == "QueryStartTime")
filter = Expression.GreaterThanOrEqual(left, right);
else if (propertyName == "QueryEndTime")
filter = Expression.LessThan(left, right);
else if (propertyName == "QueryName")
filter = Expression.Call(Expression.Property(param, typeof(TestUser).GetProperty(queryDict[propertyName])), typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), Expression.Constant(propertyVal));
else
filter = Expression.Equal(left, right); totalExpr = Expression.And(filter, totalExpr);
}
}
//Where部分条件
Expression pred = Expression.Lambda(totalExpr, param);
Expression whereExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(TestUser) }, Expression.Constant(sourceLs), pred);
//OrderBy部分排序
MethodCallExpression orderByCallExpression = Expression.Call(typeof(Queryable), queryCondition.IsDesc ? "OrderByDescending" : "OrderBy", new Type[] { typeof(TestUser), orderEntries[queryCondition.OrderField].OrderType }, whereExpression, Expression.Lambda(Expression.Property(param, orderEntries[queryCondition.OrderField].OrderStr), param)); //生成动态查询
sourceLs = sourceLs.Provider.CreateQuery<TestUser>(orderByCallExpression); return sourceLs.ToList<TestUser>();
} #endregion /// <summary>
/// 具体查询属性和实体里面属性作Mapping,当然你可以对名字规范做一个显示那样不用做映射用反射获取到直接构建表达式也行
/// 具体这里只是假设模拟了一个这种情况,使用者可以根据自身业务情况适当修改
/// </summary>
public void InitDynamicQueryMapping()
{
//查询mapping
queryDict.Add("QueryId", "Id");
queryDict.Add("QueryName", "Name");
queryDict.Add("QueryStartTime", "Birth");
queryDict.Add("QueryEndTime", "Birth");
queryDict.Add("QueryBoolean", "IsStudent");
queryDict.Add("QueryScore", "Score");
} /// <summary>
/// 制造测试数据
/// </summary>
/// <returns></returns>
public List<TestUser> GetTestData()
{
List<TestUser> testLs = new List<TestUser>();
testLs.AddRange(new TestUser[] {
new TestUser() { Id=, Name="测试1", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test001@qq.com", Score= },
new TestUser() { Id=, Name="测试2", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test002@qq.com", Score= },
new TestUser() { Id=, Name="测试3", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test003@qq.com", Score= },
new TestUser() { Id=, Name="测试4", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test004@qq.com", Score= },
new TestUser() { Id=, Name="测试5", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test006@qq.com", Score= },
new TestUser() { Id=, Name="测试6", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test007@qq.com", Score= },
new TestUser() { Id=, Name="测试7", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test008@qq.com", Score= },
new TestUser() { Id=, Name="测试8", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test009@qq.com", Score= },
new TestUser() { Id=, Name="测试9", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test010@qq.com", Score= },
new TestUser() { Id=, Name="测试10", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test011@qq.com", Score= },
new TestUser() { Id=, Name="动态测试11", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test012@qq.com", Score= },
new TestUser() { Id=, Name="动态测试12", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test013@qq.com", Score= },
new TestUser() { Id=, Name="动态测试13", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test014@qq.com", Score= },
new TestUser() { Id=, Name="动态测试14", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test015@qq.com", Score= },
new TestUser() { Id=, Name="动态测试15", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test016@qq.com", Score= },
new TestUser() { Id=, Name="动态测试16", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test017@qq.com", Score= },
new TestUser() { Id=, Name="动态测试17", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test018@qq.com", Score= },
new TestUser() { Id=, Name="动态测试18", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test019@qq.com", Score= },
new TestUser() { Id=, Name="动态测试19", Birth=new DateTime(,,), IsStudent=false, Cellphone="", Email="test020@qq.com", Score= },
new TestUser() { Id=, Name="动态测试20", Birth=new DateTime(,,), IsStudent=true, Cellphone="", Email="test021@qq.com", Score= },
});
return testLs;
} /// <summary>
/// 打印测试数据
/// </summary>
/// <param name="resultLs"></param>
public void PrintResult(List<TestUser> resultLs)
{
foreach (TestUser item in resultLs)
{
Console.WriteLine("序号:{0},姓名:{1},生日:{2},是否在读:{3},联系手机:{4},邮箱:{5},分数:{6}", item.Id, item.Name, item.Birth, item.IsStudent ? "是" : "否", item.Cellphone, item.Email, item.Score);
}
}
} /// <summary>
/// 业务实体类-你可以想象成你业务中需要实际使用的类
/// </summary>
public class TestUser
{
public TestUser() { } public int Id { get; set; } public string Name { get; set; } public DateTime Birth { get; set; } public bool IsStudent { get; set; } public string Cellphone { get; set; } public string Email { get; set; } public int Score { get; set; }
} /// <summary>
/// 排序帮助类
/// </summary>
public class OrderEntry
{
public string OrderStr { get; set; } public Type OrderType { get; set; }
} /// <summary>
/// 业务查询条件类-实际使用中你可以根据自己的需要构建你的查询条件类
/// </summary>
public class QueryCondition
{
public QueryCondition() { } public QueryCondition(int? queryId, string queryName, DateTime? queryStart, DateTime? queryEnd, bool? queryBoolean, int? queryScore, int orderField, bool isDesc)
{
QueryId = queryId;
QueryName = queryName;
QueryStartTime = queryStart;
QueryEndTime = queryEnd;
QueryBoolean = queryBoolean;
QueryScore = queryScore;
OrderField = orderField;
IsDesc = isDesc;
} public int? QueryId { get; set; } public string QueryName { get; set; } public DateTime? QueryStartTime { get; set; } public DateTime? QueryEndTime { get; set; } public bool? QueryBoolean { get; set; } public int? QueryScore { get; set; } public int OrderField { get; set; } public bool IsDesc { get; set; }
}
}
}
动态LINQ(Lambda表达式)构建的更多相关文章
- 【转】EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句
传统的操作数据库方式,筛选数据需要用StringBuilder拼接一大堆的WHERE子句. 在Entity Framework中,代码稍有不慎就会造成巨大性能消耗,如: using(var db=ne ...
- 动态创建Lambda表达式实现高级查询
需求简介 最近这几天做的东西总算是回归咱的老本行了,给投资管理项目做一个台账的东西,就是类似我们的报表.其 中有一个功能是一个高级查询的需求,在查询条件方面大概有7.8个查询条件.需求就是如果一个条件 ...
- 动态组合lambda 表达式
//记录实体集合—动态组合lambda 表达式 Expression<Func<AdEntity, bool>> thirdWhere = p => p.Observer ...
- easyui datagrid remoteSort的实现 Controllers编写动态的Lambda表达式 IQueryable OrderBy扩展
EF 结合easy-ui datagrid 实现页面端排序 EF动态编写排序Lambda表达式 1.前端页面 var mainListHeight = $(window).height() - 20; ...
- 动态创建 Lambda 表达式
首先我们看一个简单 Lambda 表达式的构成. i => i > 5 在这个表达式中,"i" 被称为 Parameter,"i > 5" 是 ...
- LinQ—Lambda表达式
概述 本篇博客主要解说lambda表达式,在这里将它的来龙去脉,主要是从托付,匿名函数这些方面过度讲的,当然,在讲托付和匿名函数的时候,主要是从Lambda的角度出发讲的,可能它们还具有其他的一些作用 ...
- 动态拼接lambda表达式树
前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...
- [2014-12-30]如何动态构造Lambda表达式(动态构造Lambda查询条件表达式)
声明 本文对Lambda表达式的扩展,示例代码来源于网络. 场景描述 web开发查询功能的时候,如果查询条件比较多,就会遇到动态组合查询条件的情况.在手写sql的情况下,我们一般会根据传入的参数,针对 ...
- 使用Expression动态创建lambda表达式
using System;using System.Linq.Expressions;using System.Reflection; namespace Helper{ public class L ...
- C#动态创建lambda表达式
/// <summary> /// 创建lambda表达式:p=>true /// </summary> /// <typeparam name="T&q ...
随机推荐
- java中计算一段时间内白天的时间和夜晚的时间
之前,采用拼接字符串的形式,不断地在Date类型和Long类型之间转换,实在是太过于麻烦,后来采取了这种思路:假设我们将22:00 ~ 10:00 视为夜间时间,则我们先计算出10:00 相对于当天的 ...
- UINavigationController + UIScrollView组合,视图尺寸的设置探秘(二)
承接上文,我想把view布局修改为如下模式,让ScrollView长在NavigationBar的下方,这总不会有遮挡的问题了吧: story board内容如下,主要是右侧视图蓝色区域添加了Scro ...
- Leveling Ground(数论,三分法,堆)
Leveling Ground(数论,三分法,堆) 给定n个数和a,b每次可以选择一段区间+a,-a,+b或-b,问最少操作几次能把他们都变成0.n<=1e5. 首先差分一下序列,问题就会变成了 ...
- LB 负载均衡的层次结构(转)
http://blog.csdn.net/mindfloating/article/details/51020767 作为后端应用的开发者,我们经常开发.调试.测试完我们的应用并发布到生产环境,用户就 ...
- P2700 逐个击破
题意:现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的, 现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这K ...
- peaks
给定一个无向图,点有点权边有边权 Q次询问,每次询问从点v开始只经过边权<=x的边能到达所有点中点权第k大值,无解输出-1 N<=1e5,M,Q<=5e5 建立大根kruskal重构 ...
- Qt 学习之路 2(2):Qt 简介
Home / Qt 学习之路 2 / Qt 学习之路 2(2):Qt 简介 Qt 学习之路 2(2):Qt 简介 豆子 2012年8月21日 Qt 学习之路 2 43条评论 Qt 是一个著名的 ...
- GUI JFrame窗体介绍:
GUI JFrame窗体介绍: https://www.cnblogs.com/-ksz/p/3422074.html
- node.js 服务器
http-server 是一个简单的零配置命令行HTTP服务器, 基于 nodeJs. 如果你不想重复的写 nodeJs 的 web-server.js, 则可以使用这个. 安装 (全局安装加 -g) ...
- Spring Cloud 监控相关
因为最近客户提出想监控Spring Cloud运行状况的需求,所以稍稍做了调研.目前了解的方法如下: Eureka Server启动后可以在根目录路径看到所有注册的Eureka Client状况 各个 ...