动态LINQ构建(实现等于不等于大于小于,like以及IN)
首先感谢园子里的“红烧狮子头”,他的工作是本文的基础,引文如下http://www.cnblogs.com/daviddai/archive/2013/03/09/2952087.html,本版本实现了类似SQL中的like与in的功能,实现了多orderby的级联排序,下面贴出代码:
一些辅助类:
public enum ConditionFlags
{
And = ,
Or = ,
} public enum RelationFlags
{
Equal = ,
NoEqual = ,
GreaterThan = ,
LessThan = ,
GreaterThanOrEqual = ,
LessThanOrEqual = ,
LikeWildcardBoth = ,
LikeLeftWildcardOnly = ,
LikeRightWildcardOnly = ,
In = ,
} public class QueryCondition
{
public string ConditionField { get; set; }
public object FieldValue { get; set; }
public ConditionFlags Condition { get; set; }
public RelationFlags Relation { get; set; }
} public class OrderByCondition
{
public string OrderField { get; set; }
public bool IsDesc { get; set; }
}
实现IEnumerable的实现方法:
public static IEnumerable<T> GetDataByDynamicQuery<T>(this IEnumerable<T> sourceList, List<QueryCondition> queryConditionList, params OrderByCondition[] orderByConditionList)
{
if (null == sourceList)
{
throw new ArgumentException("source list must not be null");
} IQueryable<T> sourceLs = sourceList.AsQueryable(); Expression finalExpr;
Expression filter, totalExpr;
filter = totalExpr = Expression.Constant(true); ParameterExpression param = Expression.Parameter(typeof(T), "n");
foreach (var item in queryConditionList ?? Enumerable.Empty<QueryCondition>())
{
//反射找出所有查询条件的属性值,如果该查询条件值为空或者null不添加动态lambda表达式
string propertyName = item.ConditionField;
var propertyVal = item.FieldValue; if (!string.IsNullOrEmpty(propertyName) && propertyVal != null && propertyVal.ToString() != string.Empty)
{
//n.property
PropertyInfo property = typeof(T).GetProperty(propertyName);
Expression left = Expression.Property(param, property);
//等式右边的值
Expression right = Expression.Constant(propertyVal);
MethodInfo containsmethod;
switch (item.Relation)
{
case RelationFlags.Equal:
if (typeof(string) == property.PropertyType)
{
containsmethod = typeof(string).GetMethod("Equals", new[] { typeof(string), typeof(string), typeof(StringComparison) }); filter = Expression.Call(containsmethod,left, right, Expression.Constant(StringComparison.OrdinalIgnoreCase));
}
else
{
filter = Expression.Equal(left, right);
}
break;
case RelationFlags.NoEqual:
filter = Expression.NotEqual(left, right);
break;
case RelationFlags.GreaterThan:
filter = Expression.GreaterThan(left, right);
break;
case RelationFlags.LessThan:
filter = Expression.LessThan(left, right);
break;
case RelationFlags.GreaterThanOrEqual:
filter = Expression.GreaterThanOrEqual(left, right);
break;
case RelationFlags.LessThanOrEqual:
filter = Expression.LessThanOrEqual(left, right);
break;
case RelationFlags.LikeWildcardBoth:
if (typeof (string) == property.PropertyType)
{
containsmethod = property.PropertyType.GetMethod("Contains", new Type[] { property.PropertyType });
filter = Expression.Call(left, containsmethod, right);
}
else
{
throw new ArgumentException(" 'like %x%' operator work on string type only ");
}
break;
case RelationFlags.LikeLeftWildcardOnly:
if (typeof (string) == property.PropertyType)
{
containsmethod = property.PropertyType.GetMethod("EndsWith", new Type[] { property.PropertyType });
filter = Expression.Call(left, containsmethod, right);
}
else
{
throw new ArgumentException(" 'like %x' operator work on string type only ");
}
break;
case RelationFlags.LikeRightWildcardOnly:
if (typeof (string) == property.PropertyType)
{
containsmethod = property.PropertyType.GetMethod("StartsWith", new Type[] { property.PropertyType });
filter = Expression.Call(left, containsmethod, right);
}
else
{
throw new ArgumentException(" 'like x%' operator work on string type only ");
}
break;
case RelationFlags.In:
Expression rightTmp, filterTmp;
Expression totalExprTmp = Expression.Constant(false);
foreach (var itemValue in propertyVal as IEnumerable ?? Enumerable.Empty<object>())
{
rightTmp = Expression.Constant(itemValue);
if (typeof(string) == property.PropertyType)
{
containsmethod = typeof(string).GetMethod("Equals", new[] { typeof(string), typeof(string), typeof(StringComparison) });
filterTmp = Expression.Call(containsmethod,left, rightTmp, Expression.Constant(StringComparison.OrdinalIgnoreCase));
}
else
{
filterTmp = Expression.Equal(left, rightTmp);
}
totalExprTmp = Expression.Or(filterTmp, totalExprTmp);
}
filter = totalExprTmp = Expression.And(totalExprTmp, Expression.Constant(true));
break;
default:
filter = Expression.Constant(true);
break;
}
switch (item.Condition)
{
case ConditionFlags.And:
totalExpr = Expression.And(totalExpr, filter);
break;
case ConditionFlags.Or:
totalExpr = Expression.Or(totalExpr.NodeType.Equals(Expression.Constant(true).NodeType) ? Expression.Constant(false) : totalExpr, filter);
break;
default:
break;
}
}
}
//Where部分条件
Expression pred = Expression.Lambda(totalExpr, param);
finalExpr = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(T) }, Expression.Constant(sourceLs), pred);
string orderByFunctionName = "OrderBy";
string orderByDescFunctionName = "OrderByDescending";
foreach (var orderbyCondition in orderByConditionList ?? Enumerable.Empty<OrderByCondition>())
{
PropertyInfo pInfo = typeof(T).GetProperty(orderbyCondition.OrderField);
//OrderBy部分排序
finalExpr = Expression.Call(typeof(Queryable), orderbyCondition.IsDesc ? orderByDescFunctionName : orderByFunctionName, new Type[] { typeof(T), pInfo.PropertyType }, finalExpr, Expression.Lambda(Expression.Property(param, pInfo), param));
orderByFunctionName = "ThenBy";
orderByDescFunctionName = "ThenByDescending";
} return sourceLs.Provider.CreateQuery<T>(finalExpr);
}
调用示例:
if (queryEntity.ApplicationIds != null && queryEntity.ApplicationIds.Length > )
{
var queryCondition = new QueryCondition
{
ConditionField = "ApplicationId",
FieldValue = queryEntity.ApplicationIds,
Condition = ConditionFlags.And,
Relation = RelationFlags.In
};
queryConditionList.Add(queryCondition);
}
if (!string.IsNullOrWhiteSpace(queryEntity.LinkPath))
{
var queryCondition = new QueryCondition();
queryCondition.ConditionField = "LinkPath";
queryCondition.FieldValue = queryEntity.LinkPath;
queryCondition.Condition = ConditionFlags.And;
queryCondition.Relation = RelationFlags.Equal;
queryConditionList.Add(queryCondition);
}
var orderByConditionList = new List<OrderByCondition>();
var orderByCondition = new OrderByCondition {OrderField = "SortIndex", IsDesc = true};
orderByConditionList.Add(orderByCondition);
var orderByConditionMenuId = new OrderByCondition {OrderField = "MenuId", IsDesc = false};
orderByConditionList.Add(orderByConditionMenuId);
return alllist.GetDataByDynamicQuery<ControlPanelMenuEntity>(queryConditionList, orderByConditionList.ToArray()).ToList();
动态LINQ构建(实现等于不等于大于小于,like以及IN)的更多相关文章
- 动态LINQ(Lambda表达式)构建
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; us ...
- 使用Expression Tree构建动态LINQ查询
这篇文章介绍一个有意思的话题,也是经常被人问到的:如何构建动态LINQ查询?所谓动态,主要的意思在于查询的条件可以随机组合,动态添加,而不是固定的写法.这个在很多系统开发过程中是非常有用的. 我这里给 ...
- 自动化测试尝试 动态Linq表达式生成 ftp上传
自动化测试尝试 1. Selenium IDE Selenium IDE is a Chrome and Firefox plugin which records and plays back u ...
- 基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式
-之动态查询,查询逻辑封装复用 基于领域驱动设计(DDD)超轻量级快速开发架构详细介绍请看 https://www.cnblogs.com/neozhu/p/13174234.html 需求 配合Ea ...
- 动态Linq(结合反射)
这篇文章决定对最近一个单机版Web程序用到的东西总结一下. 一.反射Linq之OrderBy 动态Linq结合反射对某字段排序: namespace 动态Linq { class Program { ...
- C# 动态Linq(结合反射)
这篇文章决定对最近一个单机版Web程序用到的东西总结一下. 一.反射Linq之OrderBy 动态Linq结合反射对某字段排序: namespace 动态Linq { class Program ...
- Linq技术四:动态Linq技术 -- Linq.Expressions
前面介绍了Linq的三个方面应用:Linq to SQL, Linq to XML和Linq to Object,这篇介绍一下动态Linq的实现方式及应用场景. 命名空间: System.Linq; ...
- Mybatis在xml配置文件中处理SQL中的大于小于号的方法
之前在项目中遇到了在SQL中<=不识别的问题,在Navicat中语句正常,在xml中不识别,想起来就记录一下 项目用的是Mybatis,经过网上多次查询,验证,总结方法如下: 一.使用<! ...
- EF和linq语句查询条件不等于某个参数出现的问题
where t.a!=字符串 这是错误的写法,正确为 where t.a!=字符串.trim() 其他类型变量需要保持实体类型和查询条件参数的类型是一致的,不然出现的语句可能会是 类似`Exten ...
随机推荐
- 用终端直接在桌面生成text文件
简单的两行命令: cd Desktop/ 按回车 touch 888.text 按回车就会在桌面生成名称为888的text文件 用途:做demo的时候可以加一个说明文档进去,这样下次可以很方便的查看
- 【模拟,时针分针秒针两两夹角】【没有跳坑好兴奋】hdu - 5387 (多校#8 1008)
算是最好写的一道题了吧,最近模拟没手感,一次过也是很鸡冻o(* ̄▽ ̄*)o 注意事项都在代码里,没有跳坑也不清楚坑点在哪~ #include<cstdio> #include<cst ...
- Emmet 语法大全(缩写语法/sublime 插件)
Emmet 使用类似于 CSS 选择器的语法描述元素在生成的文档树中的位置及其属性. 元素 可以使用元素名(如 div 或者 p)来生成 HTML 标签.Emmet 没有预定义的有效元素名的集合,可以 ...
- 从零单排Linux – 1 – 简单命令
从零单排Linux – 1 – 简单命令 Posted in: Linux 从零单排Linux – 1 一.Linux的简单命令: 1.忘记root密码: 读秒时按任意键进入 – e – ↓选择第二个 ...
- Java Concurrency - 线程执行器
Usually, when you develop a simple, concurrent-programming application in Java, you create some Runn ...
- 如何用代码开启“个人热点”功能?如何用代码把iOS设备设置成一个无线路由?
不好意思,你办不到.苹果不允许.因为你没有权限.
- jQuery之对话框
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http ...
- Yii zii.widgets.grid 隐藏列 方便js获取隐藏值
array( 'name' => $data->is_audit, 'value' => '$data->is_audit', 'headerHtmlOptions' => ...
- sql 截取两个字符串之间的字符
select SUBSTRING(templatepath,CHARINDEX('/',templatepath)+1,CHARINDEX('.', templatepath)-CHARINDEX(' ...
- 229. Majority Element II My Submissions Question
Total Accepted: 23103 Total Submissions: 91679 Difficulty: Medium Given an integer array of size n, ...