EF之高级查询
首先我们来看看一个页面
这里面有多选的条件,大于,小于等等,包括每个字段都有
如此多的查询条件,我们的后台该如何实现呢?
难道我们还得每个参数都去判断吗?
那得传多少参数进来才能实现这个页面的功能啊!
既然用了EF当然不能在用sql拼接了
那么我们就来看看这个页面是怎么实现的吧
首先我们来看看这个页面的参数是怎么传到后台的
这是获取查询条件的脚本
- var filterRules = new Array();
- $(op.toolbarid).find("input[type!='button'][data-disable!='true'],select[data-disable!='true']").each(function () {
- var isadd = false;
- var value = $(this).val();
- if (this.type == "checkbox" || this.type == "radio") {
- isadd = this.checked;
- } else if (value) {
- isadd = true;
- }
- if (isadd) {
- var field = $(this).data("field");
- if (!field) {
- field = this.id;
- }
- var op = $(this).data("op");
- var time_add = $(this).data("time-add");
- if (time_add || $(this).data("time-today")) {
- if (time_add) {
- value = (new Date(Date.parse(value.replace(/-/g, "/")).getTime() + parseInt(time_add) * 86400000)).Format("yyyy-MM-dd");
- } else {
- var new_value = (new Date(Date.parse(value.replace(/-/g, "/")).getTime() + 86400000)).Format("yyyy-MM-dd");
- filterRules.push({ group: $(this).data("group"), field: field, op: "<", split: $(this).data("split"), value: new_value });
- op = ">=";
- }
- }
- filterRules.push({ group: $(this).data("group"), field: field, op: op, split: $(this).data("split"), value: value });
- }
- });
- options.filterRules = filterRules;
这是请求后台传递的参数
- [{"field":"FILE_TYPE","op":"=","split":",","value":"CAD,AD"},
- {"field":"WRITE_DATE","op":">=","value":"2011-01-01"},
- {"field":"WRITE_DATE","op":"<","value":"2016-04-14"},
- {"field":"STATUS","op":"=","split":",","value":"CLOSE,C/W"}]
后台代码
- return db.AWF_FILE_MAIN.Join(db.FLOW_TASK_INFO, d => d.FILE_NO, d => d.FILE_NO, (x, y) => new { ... })
- .Where(EasyuiFilterRules.GetWPList(wm.filterRules), wm.filterRules_isand)
- .ToPageJson(wm.page, wm.pageSize, wm.field, wm.order, DateTimeJson.Create(format: "yyyy-MM-dd"));
关键代码
.Where(EasyuiFilterRules.GetWPList(wm.filterRules), wm.filterRules_isand)
接下来我们就来看看Where背后的秘密,
我们先来看看EasyuiFilterRules类
EasyuiFilterRules主要的功能就是把JSON字符串转换成WhereParameters对象
- /// <summary>
- /// Easyui搜索规则
- /// </summary>
- public class EasyuiFilterRules
- {
- /// <summary>
- /// 字段名称
- /// </summary>
- public string field { get; set; }
- /// <summary>
- /// 过滤类型,可选值有(contains-包含,equal-相等,notequal-不相等,beginwith-开头包含,endwith-结尾包含,less-小于,lessorequal-小于等于,greater-大于,greaterorequal-大于等于)
- /// </summary>
- public string op { get; set; }
- /// <summary>
- /// 要搜索的值
- /// </summary>
- public string value { get; set; }
- /// <summary>
- /// 组
- /// </summary>
- public int? group { get; set; }
- /// <summary>
- /// 分隔符
- /// </summary>
- public string split { get; set; }
- /// <summary>
- /// 方法
- /// </summary>
- public string fun { get; set; }
- /// <summary>
- /// 获取过滤参数集合根据Easyui搜索规则字符串
- /// </summary>
- /// <param name="filterRules">Easyui搜索规则字符串</param>
- /// <returns>过滤参数集合</returns>
- public static List<WhereParameters> GetWPList(string filterRules)
- {
- var ps = new List<WhereParameters>();
- if (string.IsNullOrEmpty(filterRules))
- {
- return ps;
- }
- var list = JsonConvert.DeserializeObject<List<EasyuiFilterRules>>(filterRules);
- if (list.Count == )
- {
- return ps;
- }
- int index = -;
- foreach (var item in list)
- {
- if (string.IsNullOrEmpty(item.value))
- {
- continue;
- }
- var names = item.field.Split(',');
- foreach (var name in names)
- {
- var values = item.value.Split(new string[]{item.split},StringSplitOptions.RemoveEmptyEntries);
- foreach (var value in values)
- {
- var wp = new WhereParameters(value, name, group: item.group ?? index,fun:item.fun);
- if (item.value == "is null")
- {
- wp.value = null;
- wp.isnotnull = false;
- wp.wherefun = WhereFun.Equal;
- }
- else if (item.value == "is not null")
- {
- wp.value = null;
- wp.isnotnull = false;
- wp.wherefun = WhereFun.NotEqual;
- }
- else
- {
- if (string.IsNullOrEmpty(item.op))
- {
- item.op = "contains";
- }
- switch (item.op.ToLower())
- {
- case "=":
- case "==":
- case "equal":
- case "eq": wp.wherefun = WhereFun.Equal; break;
- case "!=":
- case "neq":
- case "notequal": wp.wherefun = WhereFun.NotEqual; break;
- case "<":
- case "lt":
- case "less": wp.wherefun = WhereFun.LessThan; break;
- case "<=":
- case "lte":
- case "lessorequal": wp.wherefun = WhereFun.LessThanOrEqual; break;
- case ">":
- case "gt":
- case "greater": wp.wherefun = WhereFun.GreaterThan; break;
- case ">=":
- case "gte":
- case "greaterorequal": wp.wherefun = WhereFun.GreaterThanOrEqual; break;
- case "!c":
- case "doesnotcontain": wp.wherefun = WhereFun.NotContains; break;
- case "^c":
- case "startswith": wp.wherefun = WhereFun.StartsWith; break;
- case "c$":
- case "endswith": wp.wherefun = WhereFun.EndsWith; break;
- case "like": wp.wherefun = WhereFun.Like; break;
- case "notlike": wp.wherefun = WhereFun.NotLike; break;
- default: wp.wherefun = WhereFun.Contains; break;
- }
- }
- ps.Add(wp);
- }
- }
- index--;
- }
- return ps;
- }
- }
接着我们看看WhereHelper类
就是这个类让Where方法可以接受.Where(EasyuiFilterRules.GetWPList(wm.filterRules), wm.filterRules_isand)这样的参数
代码也是相对比较简单的
- /// <summary>
- /// 搜索条件辅助类
- /// </summary>
- public static class WhereHelper
- {
- /// <summary>
- /// 根据条件过滤数据
- /// </summary>
- /// <typeparam name="model">指定的模型</typeparam>
- /// <param name="mls">对象</param>
- /// <param name="ps">过滤参数集合</param>
- /// <param name="isand">如果为true则同一组的进行Or运算,不同组的进行And运算,否则同一组的进行And运算,不同组的进行Or运算</param>
- /// <returns>对象</returns>
- public static IQueryable<model> Where<model>(this IQueryable<model> mls, List<WhereParameters> ps, bool isand = true)
- {
- if (ps.Count == )
- {
- return mls;
- }
- return mls.Where(WhereEx<model>.Create(ps, isand).ToFun());
- }
- }
继续WhereParameters,这个类也只是用来保存一些数据信息,没什么逻辑
- /// <summary>
- /// 过滤参数
- /// </summary>
- public class WhereParameters
- {
- /// <summary>
- /// 构造函数
- /// </summary>
- public WhereParameters()
- {
- }
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="value">要匹配的值</param>
- /// <param name="name">要匹配的字段名称</param>
- /// <param name="wherefun">匹配方法</param>
- /// <param name="isnotnull">值不为空才执行</param>
- /// <param name="group">组</param>
- /// <param name="fun">方法</param>
- public WhereParameters(object value, string name, WhereFun wherefun = WhereFun.Contains, bool isnotnull = true, int group = ,string fun="")
- {
- this.value = value;
- this.name = name;
- this.wherefun = wherefun;
- this.isnotnull = isnotnull;
- this.group = group;
- this.fun = fun;
- }
- /// <summary>
- /// 判断是否要添加查询条件
- /// </summary>
- /// <returns>是否</returns>
- public bool IsAddWhere(Type type)
- {
- if (this.isnotnull && IsValueNull(type))
- {
- return false;
- }
- return true;
- }
- /// <summary>
- /// 判断值是否为空
- /// </summary>
- /// <returns></returns>
- public bool IsValueNull(Type type)
- {
- return string.IsNullOrEmpty(Convert.ToString(this.value));
- }
- /// <summary>
- /// 要匹配的值
- /// </summary>
- public object value { get; set; }
- /// <summary>
- /// 要匹配的字段名称
- /// </summary>
- public string name { get; set; }
- /// <summary>
- /// 匹配方法
- /// </summary>
- public WhereFun wherefun { get; set; }
- /// <summary>
- /// 值不为空才执行
- /// </summary>
- public bool isnotnull { get; set; }
- /// <summary>
- /// 组
- /// </summary>
- public int group { get; set; }
- /// <summary>
- /// 方法
- /// </summary>
- public string fun { get; set; }
- }
WhereParameters类所用到的枚举,也是查询所支持的比较方法
- /// <summary>
- /// 匹配方法
- /// </summary>
- public enum WhereFun
- {
- /// <summary>
- /// 包含
- /// </summary>
- Contains = ,
- /// <summary>
- /// 相等
- /// </summary>
- Equal = ,
- /// <summary>
- /// 不相等
- /// </summary>
- NotEqual = ,
- /// <summary>
- /// 大于
- /// </summary>
- GreaterThan = ,
- /// <summary>
- /// 大于等于
- /// </summary>
- GreaterThanOrEqual = ,
- /// <summary>
- /// 小于
- /// </summary>
- LessThan = ,
- /// <summary>
- /// 小于等于
- /// </summary>
- LessThanOrEqual = ,
- /// <summary>
- /// 开始包含
- /// </summary>
- StartsWith = ,
- /// <summary>
- /// 结束包含
- /// </summary>
- EndsWith = ,
- /// <summary>
- /// 不包含
- /// </summary>
- NotContains = ,
- /// <summary>
- /// 包含(支持通配符)
- /// </summary>
- Like = ,
- /// <summary>
- /// 不包含(支持通配符)
- /// </summary>
- NotLike =
- }
重中之重还是WhereEx<T>类了,这是关键,主要是用了Expression表达式树实现的
- /// <summary>
- /// Where表达式
- /// </summary>
- /// <typeparam name="T">指定的模型</typeparam>
- public class WhereEx<T>
- {
- /// <summary>
- /// 表达式
- /// </summary>
- private Expression ex { get; set; }
- /// <summary>
- /// 模型参数
- /// </summary>
- private ParameterExpression p_model { get; set; }
- /// <summary>
- /// 构造参数
- /// </summary>
- /// <param name="ps">过滤参数</param>
- /// <param name="isand">如果为true则同一组的进行Or运算,不同组的进行And运算,否则同一组的进行And运算,不同组的进行Or运算</param>
- /// <returns>Where表达式</returns>
- public static WhereEx<T> Create(List<WhereParameters> ps, bool isand = true)
- {
- var model = new WhereEx<T>();
- model.p_model = Expression.Parameter(typeof(T), "p_model_where");
- if (ps == null || ps.Count == )
- {
- return model;
- }
- var grouplist = ps.GroupBy(d => d.group);
- if (isand)
- {
- foreach (var item in grouplist)
- {
- model.And(item.ToArray());
- }
- }
- else
- {
- foreach (var item in grouplist)
- {
- model.Or(item.ToArray());
- }
- }
- return model;
- }
- /// <summary>
- /// 构造参数
- /// </summary>
- /// <param name="value">要匹配的值</param>
- /// <param name="name">要匹配的字段名称</param>
- /// <param name="wherefun">匹配方法</param>
- /// <param name="isnotnull">值不为空才执行</param>
- /// <returns>Where表达式</returns>
- public static WhereEx<T> Create(object value, string name, WhereFun wherefun = WhereFun.Contains, bool isnotnull = true)
- {
- var model = new WhereEx<T>();
- model.p_model = Expression.Parameter(typeof(T), "p_model_where");
- model.And(new WhereParameters(value, name, wherefun, isnotnull));
- return model;
- }
- /// <summary>
- /// Where表达式And运算
- /// </summary>
- /// <param name="value">要匹配的值</param>
- /// <param name="name">要匹配的字段名称</param>
- /// <param name="wherefun">匹配方法</param>
- /// <param name="isnotnull">值不为空才执行</param>
- /// <returns>Where表达式</returns>
- public WhereEx<T> And(object value, string name, WhereFun wherefun = WhereFun.Contains, bool isnotnull = true)
- {
- return this.And(new WhereParameters(value, name, wherefun, isnotnull));
- }
- /// <summary>
- /// Where表达式Or运算
- /// </summary>
- /// <param name="value">要匹配的值</param>
- /// <param name="name">要匹配的字段名称</param>
- /// <param name="wherefun">匹配方法</param>
- /// <param name="isnotnull">值不为空才执行</param>
- /// <returns>Where表达式</returns>
- public WhereEx<T> Or(object value, string name, WhereFun wherefun = WhereFun.Contains, bool isnotnull = true)
- {
- return this.Or(new WhereParameters(value, name, wherefun, isnotnull));
- }
- /// <summary>
- /// Where表达式And运算
- /// </summary>
- /// <param name="ps">过滤参数(多个参数时先进行Or运算)</param>
- /// <returns>Where表达式</returns>
- public WhereEx<T> And(params WhereParameters[] ps)
- {
- var psex = this.GetWhereEx(false, ps);
- if (psex != null)
- {
- if (this.ex == null)
- {
- this.ex = Expression.Constant(true, typeof(bool));
- }
- this.ex = Expression.AndAlso(this.ex, psex);
- }
- return this;
- }
- /// <summary>
- /// Where表达式Or运算
- /// </summary>
- /// <param name="ps">过滤参数(多个参数时先进行And运算)</param>
- /// <returns>Where表达式</returns>
- public WhereEx<T> Or(params WhereParameters[] ps)
- {
- var psex = this.GetWhereEx(true, ps);
- if (psex != null)
- {
- if (this.ex == null)
- {
- this.ex = Expression.Constant(false, typeof(bool));
- }
- this.ex = Expression.OrElse(this.ex, psex);
- }
- return this;
- }
- /// <summary>
- /// Where表达式转方法
- /// </summary>
- /// <returns>方法</returns>
- public Expression<Func<T, bool>> ToFun()
- {
- if (this.ex == null)
- {
- this.ex = Expression.Constant(true, typeof(bool));
- }
- return Expression.Lambda<Func<T, bool>>(this.ex, this.p_model);
- }
- /// <summary>
- /// 根据过滤参数获取表达式
- /// </summary>
- /// <param name="isand">是否是And运算</param>
- /// <param name="ps">过滤参数集合</param>
- /// <returns>表达式</returns>
- private Expression GetWhereEx(bool isand, params WhereParameters[] ps)
- {
- Expression psex = Expression.Constant(isand);
- if (ps.Length == )
- {
- return psex;
- }
- bool isaddps = false;
- #region 循环参数进行运算
- foreach (var item in ps)
- {
- var pro = this.p_model.Type.GetProperty(item.name);
- if (pro == null)
- continue;
- if (!item.IsAddWhere(pro.PropertyType))
- {
- continue;
- }
- isaddps = true;
- var pro_type = pro.PropertyType;
- Expression left = Expression.Property(this.p_model, pro);
- if (!string.IsNullOrEmpty(item.fun))
- {
- item.fun = item.fun.ToLower();
- if (item.fun == "length")
- {
- left = Expression.Property(left, "Length");
- pro_type = typeof(int);
- }
- }
- Expression right = Expression.Constant(null);
- if (item.value!=null)
- {
- if (pro_type.IsGenericType && pro_type.GetGenericTypeDefinition() == typeof(Nullable<>))
- {
- right = Expression.Constant(Convert.ChangeType(item.value, (new System.ComponentModel.NullableConverter(pro_type)).UnderlyingType), pro_type);
- }
- else
- {
- right = Expression.Constant(Convert.ChangeType(item.value, pro_type), pro_type);
- }
- }
- Expression body = null;
- if (item.wherefun == WhereFun.Contains || item.wherefun == WhereFun.StartsWith || item.wherefun == WhereFun.EndsWith)
- {
- body = Expression.AndAlso(Expression.NotEqual(left, Expression.Constant(null, pro_type)), Expression.Call(left, pro_type.GetMethod(item.wherefun.ToString(), new Type[] { typeof(string) }), right));
- }
- else if (item.wherefun == WhereFun.NotContains)
- {
- body = Expression.AndAlso(Expression.NotEqual(left, Expression.Constant(null, pro_type)), Expression.Not(Expression.Call(left, pro_type.GetMethod(WhereFun.Contains.ToString(), new Type[] { typeof(string) }), right)));
- }
- //else if (item.wherefun == WhereFun.Like)
- //{
- // var like = typeof(System.Data.Entity.SqlServer.SqlFunctions).GetMethod("PatIndex", new Type[] { typeof(string), typeof(string) });
- // body = Expression.GreaterThan(Expression.Call(null, like, right, left), Expression.Constant(0, typeof(int?)));
- //}
- //else if (item.wherefun == WhereFun.NotLike)
- //{
- // var like = typeof(System.Data.Entity.SqlServer.SqlFunctions).GetMethod("PatIndex", new Type[] { typeof(string), typeof(string) });
- // body = Expression.Equal(Expression.Call(null, like, right, left), Expression.Constant(0, typeof(int?)));
- //}
- else if (item.wherefun == WhereFun.Equal)
- {
- if (item.IsValueNull(pro_type) && pro_type == typeof(string))
- {
- body = Expression.Call(null, typeof(string).GetMethod("IsNullOrEmpty", new Type[] { typeof(string) }), left);
- }
- else
- {
- body = Expression.Equal(left, right);
- }
- }
- else if (item.wherefun == WhereFun.NotEqual)
- {
- if (item.IsValueNull(pro_type) && pro_type == typeof(string))
- {
- body = Expression.Not(Expression.Call(null, typeof(string).GetMethod("IsNullOrEmpty", new Type[] { typeof(string) }), left));
- }
- else
- {
- body = Expression.NotEqual(left, right);
- }
- }
- else
- {
- #region 让字符串支持大于小于比较
- if (pro_type == typeof(string))
- {
- left = Expression.Call(left, pro_type.GetMethod("CompareTo", new Type[] { typeof(string) }), right);
- right = Expression.Constant();
- }
- #endregion
- if (item.wherefun == WhereFun.GreaterThan)
- {
- body = Expression.GreaterThan(left, right);
- }
- else if (item.wherefun == WhereFun.GreaterThanOrEqual)
- {
- body = Expression.GreaterThanOrEqual(left, right);
- }
- else if (item.wherefun == WhereFun.LessThan)
- {
- body = Expression.LessThan(left, right);
- }
- else if (item.wherefun == WhereFun.LessThanOrEqual)
- {
- body = Expression.LessThanOrEqual(left, right);
- }
- if (body != null && pro_type == typeof(string))
- {
- body = Expression.AndAlso(Expression.NotEqual(Expression.Property(this.p_model, pro), Expression.Constant(null, pro_type)), body);
- }
- }
- if (isand)
- {
- psex = Expression.AndAlso(psex, body);
- }
- else
- {
- psex = Expression.OrElse(psex, body);
- }
- }
- #endregion
- if (isaddps)
- {
- return psex;
- }
- else
- {
- return null;
- }
- }
- }
最后附一些其它用法
EF之高级查询的更多相关文章
- MongoDB高级查询详细
前言 前几篇,老玩家绕道即可,新手晚上闲着也是蛋疼,不如把命令敲一边,这样你就会对MongoDB有一定的掌握啦.如果没有安装MongoDB去看我的上一篇博客 MongoDB下载安装与简单增删改查 前 ...
- T-SQL高级查询语句
高级查询 1.连接查询,对结果集列的扩展select * from info select * from info,nation #形成笛卡尔积select * from info,nation wh ...
- SQL Server高级查询
简介 关于数据库,我们经常会听说"增查删改"之类的词语,听起来很简单,但是如果想要准确的获取到需要的数据的话,还是要花点功夫的.下面由我来和大家谈谈高级查询的用法以及和普通查询的区 ...
- mongodb高级查询
前几篇,老玩家绕道即可,新手晚上闲着也是蛋疼,不如把命令敲一边,这样你就会对MongoDB有一定的掌握啦.如果没有安装MongoDB去看我的上一篇博客 MongoDB下载安装与简单增删改查 前奏:启 ...
- MySQL高级查询语句
高级查询: 一:多表连接 1.select Info.Code,Info.Name,Nation.Name from Info,Nation where Info.Nation = Nation.Co ...
- 10月17日下午MySQl数据库CRUD高级查询
高级查询:1.连接查询 #适用于有外键关系的 没有任何关系没法用select * from Info,Nation #同时查询这俩表并把两表每个数据相互组合,形成笛卡尔积 select * from ...
- Mysql 基础 高级查询
在西面内容中 car 和 nation 都表示 表名 1.无论 高级查询还是简单查询 都用 select.. from..语句 from 后面 加表名 可以使一张表也可以是 ...
- LinQ 高级查询
高级查询 模糊查(包含):.Contains(name) 开头:.StartsWith(name) 结尾:.EndsWith(name) 个数:.Count() 最大值:Max(r => r.p ...
- SNF开发平台WinForm之五-高级查询使用说明-SNF快速开发平台3.3-Spring.Net.Framework
5.1运行效果: 5.2开发实现: 1.按上面效果来说,先来看一下在程序当中如果调用.第一步在页面拖拽一个按钮为“高级查询”,事件上写下如下代码: 如果是单表查询的话,只需要传GridView就行,如 ...
随机推荐
- [前端 2]常用的JQuery和Dom页面取值与赋值
导读:书到用时方恨少,需要基础知识的时候,才悔恨自己没有总结学习好.前段时间调了好长时间的页面,突然发现自己之前不怎么在意的取值和赋值,真的是自己一个很薄弱的地方,有时候查半天都找不到一个对的,现在用 ...
- 延迟jquery,ready事件触发的时间
$.holdReady(true);//holdReady必须在ready()方法调用之前来调用,来延迟ready()方法的执行 $(document).ready(function(){ conso ...
- OSI(Open System Interconnection)网络模型
OSI模型是国际互连网标准化组织(International Standards Organizations ISO)所定义的,为了使网络的各个层次有标准.这个模型一般被称为“ISO OSI(Open ...
- TortoiseSVN文件夹图标不显示的解决方法
是否遇到过TortoiseSVN安装好后,发现文件夹的图标还是Windows默认的图标? 下面通过简单几步解决图标不显示的问题. 1/6 "Win + R"打开运行框,输入&quo ...
- Oracle 11g 客户端 下载地址
摘自: http://blog.csdn.net/davidhsing/article/details/8271845 Oracle Database Instant Client 11g 11.2. ...
- shp地图解析(不用AE)
AE太重型,还收费,如果只是加载地图作为底图,可以用纯C#实现.线类型用得最多,以下是线类型的数据结构: 总体架构 文件头 记录头 记录内容 记录头 记录内容 ............ 记录头 记录内 ...
- C puzzles详解【6-8题】
第六题 #include<stdio.h> int main() { ; switch(a) { ': printf("ONE\n"); break; ': print ...
- c#操作xml增删改查
1.首先新建一个xml文件(Root是我写上的) 2. 3.直接上代码,更直观 (1)初始化xml /// <summary> /// 初始化xml /// </summary> ...
- 发送Ajax请求获取JSON格式数据
Aspx前端页面: <script type="text/javascript"> $(function () { $.getJSON("Ajax/TestA ...
- NSLog的使用
1.NSLog会将字符串打印在两个地方:操作系统的控制台和IDE的控制台. 2.对于NSLog来说,它打印的一个目的地并非控制台,而是系统文件“system.log”. 它另一个输出的目的地并非IED ...