Linq To Entities中的动态排序
换了工作有一个月了,一样的工作、一样的代码、一样的体力活仍就……
Linq To Entityes 也是不新玩意了,近半年来也一直与之打交道,但一直也没对其深究过。今天新加的功能要对所有列支持排序,这也不是什么高难度的工作了,对与TSQL来说是写过几百遍了,但在Linq To Enitities中有点小恶心。
Linq To Entityes中的对象是个Queryable类型的,Queryable.OrderBy()方法的参数是一个Lamdba
source.OrderBy(t=>t.ID).Skip(0).Take(10)
表达式。第一个想到的便是用字段名反射出类型,如
source.OrderBy(t=>t.GetType().GetField(“ID”)).Skip(0).Take(10);
而运行时会报“无法识别GetField()方法”。
Linq实际上是一个表达式树,是基于语言级别的代码,OrderBy中需要一个表达式树。
在老外的网站上找到了如下代码,豁然开朗
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "OrderBy");
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "OrderByDescending");
}
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "ThenBy");
}
public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "ThenByDescending");
}
static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
{
string[] props = property.Split('.');
Type type = typeof(T); ParameterExpression arg = Expression.Parameter(type, "x");
Expression expr = arg; foreach (string prop in props)
{
// use reflection (not ComponentModel) to mirror LINQ
PropertyInfo pi = type.GetProperty(prop); expr = Expression.Property(expr, pi); type = pi.PropertyType;
}
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
object result = typeof(Queryable).GetMethods().Single(method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] { source, lambda });
return (IOrderedQueryable<T>)result;
}
上面的代码满足所有的排序功能了,我的项目中只需要对单列排序,所以对代码做了简化
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="property">排序字段</param>
/// <param name="isAscdening"></param>
/// <returns></returns>
static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, bool isAscdening)
{
Type type = typeof(T);
ParameterExpression arg = Expression.Parameter(type, "x");
Expression expr = arg;
PropertyInfo pi = type.GetProperty(property);
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
object result;
if (true == isAscdening)
{
result = typeof(Queryable).GetMethods().
Single(method => method.Name == "OrderBy" && method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2 && method.GetParameters().Length == 2).
MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] { source, lambda });
}
else
{
result = typeof(Queryable).GetMethods().
Single(method => method.Name == "OrderByDescending" && method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2 && method.GetParameters().Length == 2).
MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] { source, lambda });
}
return (IOrderedQueryable<T>)result;
}
还可以将方法做Queryable的扩展方法,使用起来会更方便
根据列名动态生成查询
static IQueryable<T> MakeQuery<T>(IQueryable<T> source, string colName, string colValue)
{
Type theType = typeof(T);
//创建一个参数c
ParameterExpression param = Expression.Parameter(typeof(T), "c");
//c.City=="London"
Expression left = Expression.Property(param,typeof(T).GetProperty(colName));
Expression right = Expression.Constant(colValue);
Expression filter = Expression.Equal(left, right); Expression pred = Expression.Lambda(filter, param);
//Where(c=>c.City=="London")
Expression expr = Expression.Call(typeof(Queryable), "Where",
new Type[] { typeof(T) },
Expression.Constant(source), pred);
//生成动态查询
IQueryable<T> query = source.AsQueryable()
.Provider.CreateQuery<T>(expr);
return query;
}
Linq To Entities中的动态排序的更多相关文章
- LINQ to Entities 中的查询
MSDN地址:https://msdn.microsoft.com/zh-cn/library/bb399367%28v=vs.100%29.aspx .NET Framework 4 查询是一种从数 ...
- LINQ中的动态排序
使用Linq动态属性排序 使用反射: public static Func<T,Tkey> DynamicLambda<T, Tkey>(string propertyName ...
- .net mvc datatables中orderby动态排序
今天在做项目中用datatables的排序来做筛选,不过人比较懒,不想写那么多的关于排序的代码,于是寻思这在度娘上找找,结果不负有心人啊,更感谢贴出此贴的哥们,来源:http://blog.csdn. ...
- Linq to Entities中无法构造实体或复杂类型
EF中在使用linq就行查询select时不能直接使用自动映射生成的类,需要在单独声明一个类或者使用匿名类在查询完成后再转为对应的对象. public partial class WebForm1 : ...
- 在linq to entities中无法使用自定义方法
来源: http://support.microsoft.com/kb/2588635/zh-tw (繁体)
- LINQ to Entities 查询中的标准查询运算符
投影和筛选方法 投影指的是转换的结果集到所需的窗体中的元素. 例如,可以从结果集中的每个对象投影所需的属性子集,可以投影一个属性并对其执行数学计算,也可以从结果集投影整个对象. 投影方法有 Selec ...
- Linq To Entities 及其相关(进阶)
上篇我们讲解了Linq To Entities的一些基本操作,这篇我们主要是讲解一些比较高级的东西:存储过程查询,SQL语句查询以及表达式树. 存储过程 首先来讲解存储过程查询. //Query a ...
- LINQ to Entities不识别方法***,因此该方法无法转换为存储表达式
我的程序里有这么一段代码: order.OrderExpressInfo = (from oei in orderExpressRepository.Entities where oei.OrderI ...
- linq扩展之动态排序
前两天看QQ群里面,一位朋友问的问题,说在linq中怎么实现动态排序呢,自己想了半天,没有头绪,网上找了下相关的资料,看了下,收益挺多,记录下来. 之前我们没有如果不知道动态排序的方法的话,我们可能会 ...
随机推荐
- css搞定所有垂直居中问题
单行文本 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...
- CSS--浮动与定位
*浮动布局能够实现横向多列布局. 1.在网页中,元素有三种布局模型: 1.流动模型(Flow) 2.浮动模型 (Float) 3.层模型(Layer) 流动(Flow)是默认的网页布局模式.流动布局模 ...
- 数据结构( Pyhon 语言描述 ) — — 第4章:数据和链表结构
数据结构是表示一个集合中包含的数据的一个对象 数组数据结构 数组是一个数据结构 支持按照位置对某一项的随机访问,且这种访问的时间是常数 在创建数组时,给定了用于存储数据的位置的一个数目,并且数组的长度 ...
- Vue微信自定义分享时安卓系统config:ok,ios系统config:invalid signature签名错误,或者安卓和ios二次分享时均config:ok但是分享无效的解决办法
简述需求:要求指定页面可以进行微信自定义分享(自定义标题,描述,图片,链接),剩下的页面隐藏所有基础接口.二次分享依然可以正常使用,切换至其他页面也可以正常进行自定义分享. 这两天在做微信自定义分享的 ...
- js作用域的几个问题
按照<权威指南>的说法,全局的变量作用域是全局性的,在js代码中,他处处都有定义.而在函数之内声明的变量,就只有在函数体内有定义了.函数的参数也是局部变量,他们只在函数体内部有定义.在函数 ...
- HDU 5421 Victor and String
Victor and String Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on HDU. Orig ...
- python006 Python3 运算符
Python3 运算符什么是运算符?本章节主要说明Python的运算符.举个简单的例子 4 +5 = 9 . 例子中,4 和 5 被称为操作数,"+" 称为运算符.Python语言 ...
- 谁才是最强战舰!-From 南京理工大学第八届程序设计大赛(校外镜像),博弈~~
谁才是最强战舰! Time Limit: 1000MS Memory Limit: 65536KB Description 依阿华来到镇守府的第一件事情,就是找大和solo!然而这并不是什么好消息,说 ...
- 配置standby redo log
Data Guard在最大保护和最高可用性模式下,Standby数据库必须配置standby redo log,通过下面的实验展示创建的原则和过程. 1.原则1).standby redo log的文 ...
- 公钥加密算法那些事 | RSA 与 ECC 系统对比
一.背景 据记载,公元前 400 年,古希腊人发明了置换密码.1881 年世界上的第一个电话保密专利出现.在第二次世界大战期间,德国军方启用「恩尼格玛」密码机,密码学在战争中起着非常重要的作用. 随着 ...