我们一般在学习Linq查询时,查询条件都是写死的。但是我们在实际使用过程中肯定不能这样,而是需要动态创建Linq查询条件,这里我们就需要用到Linq.Expression,用Expression来创建查询条件。

            DataTable dt = new DataTable();dt.Columns.Add("ID", typeof(int));dt.Columns.Add("Name", typeof(string));dt.Columns.Add("Height", typeof(float));for(int i=0; i<1000;i++){dt.Rows.Add(i + 1, "HSC" + (i + 1).ToString(), (i + 1) * 1.21);}

我们这里用DataTable为数据源举例,因为网上linq to DataTable的动态查询示例实在太少了。请见下面代码:我们有一个3列的DataTable dt,我们需要筛选出Height<5.0的所有行。

如果写死查询条件的话非常简单,就下面一句话:

var query = dt.AsEnumerable().Where(s => s.Field<float>("Height") < 5.0).Select(s => s);

或者用函数委托,如下面的写法,但是这也是写死的查询。

Func<DataRow, bool> fun = r => r.Field<float>("Height") < 5.0;
var q = dt.AsEnumerable().Where(fun).Select(r => r);

或者用下面的写死的Expression也可以。

Expression<Func<DataRow, bool>> exp = s => s.Field<float>("Height")<5.0;
var q1 = dt.AsEnumerable().Where(exp.Compile()).Select(s => s);

但是我们需要的是动态创建查询条件,在网上搜索了2天,看了各种关于Expression和Expression tree的介绍,如果只是通过对象的属性来筛选的话还是比较简单的,用ParameterExpresssion表示DataRow, MemberExpression表示属性,ConstanExpress表示常量,最后在用一下Expression.LessThan()就可以了。但是我们如果把DataRow.Field当作属性来用(我一开始就是这么做的),那编译始终不过。Field是DataRow的一个方法,这里我们就要用反射来获取方法,再用MethodCallExpression表示DataRow.Field()方法,然后在获取对应列的数据DataRow.Field(“Height"),才可以拿来比较用。

但是网络上关于如何使用DataRow.Field()方法反射的Express实在是太少了,看了N多文章还是一知半解。就算有一些看似可以的方法,也没有写清楚如何在Linq里面调用。

这里我把我摸索出来的成功的方法写出来供大家参考,希望大家可以少走一些弯路。

        private Func<DataRow, bool> GetLambdaExp(){ParameterExpression r = Expression.Parameter(typeof(DataRow), "r"); //DataRow参数:rConstantExpression expHeight = Expression.Constant("Height", typeof(string)); //"Height" 字符串常量List<Expression> list = new List<Expression>();list.Add(r); list.Add(expHeight); //参数列表:DataRow, "Height"//获取Field方法反射 MethodInfo,!!!一定需要MakeGenericMethod!!!, 其中的float类型为r.Field<float>("Height")的返回值类型MethodInfo mi = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) }).MakeGenericMethod(typeof(float));MethodCallExpression MC = Expression.Call(null, mi, list); //创建MethodCallExpressionConstantExpression c5 = Expression.Constant((float)5.0, typeof(float));//创建float常量5.0Expression con = Expression.LessThan(MC, c5); //Expression: r.Field<float>("Height")<5.0var expLam = Expression.Lambda<Func<DataRow, bool>>(con, r);//Func<DataRow, bool> Expression//var q = dt.AsEnumerable().Where(expLam.Compile()).Select(s => s);//如果需要直接调用return expLam.Compile();}

最后Linq调用我们创建好的动态查询Expression

var q = dt.AsEnumerable().Where(GetLambdaExp()).Select(r => r);
//用Expression动态创建和上面类似的查询

这里只是用MethodInfo和Expression实现了对于DataRow的Field的最基本的动态查询函数,各位自己再完善一下,加入各种组合查询条件。

-------------------------------------------------------------------- 分割线 ---------------------------------------------------------------

这里我又做了一个自定义的动态Linq查询,自定义的查询条件存储在Dictionary里面,然后根据Dictionary里面的条件创建动态Linq Expression查询。

private void bt_TestMapping_Click(object sender, EventArgs e){Dictionary<string, string> FilterExpression = new Dictionary<string, string>();FilterExpression.Add("`Height`>5.0", "AND");FilterExpression.Add("`ID`<=10", "AND");FilterExpression.Add("`Name`!='HSC100'", "AND");FilterExpression.Add("`Age`>2", "AND");FilterExpression.Add("`Weight`>1.20", "AND");ParameterExpression r = Expression.Parameter(typeof(DataRow), "r"); //DataRow参数:rExpression con = Expression.Constant(true); //All nested conditionsforeach (string key in FilterExpression.Keys){string[] conArr = SplitConditionStr(key);Type FieldType = dt.Columns[conArr[0]].DataType;ConstantExpression expFieldName = Expression.Constant(conArr[0], typeof(string)); //"Height" 字符串常量ConstantExpression expValue;// = Expression.Constant(conArr[2], FieldType);//创建float常量5.0 }switch (FieldType.Name){case "Single": { expValue = Expression.Constant(float.Parse(conArr[2]), FieldType); } break;case "Double": { expValue = Expression.Constant(double.Parse(conArr[2]), FieldType); } break;case "Int32": { expValue = Expression.Constant(int.Parse(conArr[2]), FieldType); } break;case "Int64": { expValue = Expression.Constant(long.Parse(conArr[2]), FieldType); } break;default: { expValue = Expression.Constant(conArr[2], FieldType); } break;}List<Expression> list = new List<Expression>();list.Add(r); list.Add(expFieldName); //参数列表:DataRow, "Height"MethodInfo mi = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) }).MakeGenericMethod(FieldType);MethodCallExpression MC = Expression.Call(null, mi, list); //创建MethodCallExpressionExpression SingleExpCon; switch (conArr[1]){case ">=": { SingleExpCon = Expression.GreaterThanOrEqual(MC, expValue); } break;case "<=": { SingleExpCon = Expression.LessThanOrEqual(MC, expValue); } break;case "!=": { SingleExpCon = Expression.NotEqual(MC, expValue); } break;case ">": { SingleExpCon = Expression.GreaterThan(MC, expValue); } break;case "<": { SingleExpCon = Expression.LessThan(MC, expValue); } break;case "=": { SingleExpCon = Expression.Equal(MC, expValue); } break;default: { SingleExpCon = Expression.Equal(MC, expValue); } break;}switch (FilterExpression[key].ToUpper()){case "AND": { con = Expression.And(con, SingleExpCon); } break;case "OR": { con = Expression.Or(con, SingleExpCon); }; break;case "AND NOT": { con = Expression.And(con, Expression.Not(SingleExpCon)); }; break;case "OR NOT": { con = Expression.Or(con, Expression.Not(SingleExpCon)); }; break;default: con = Expression.Add(con, SingleExpCon); break;}}//MessageBox.Show(con.ToString());var expLam = Expression.Lambda<Func<DataRow, bool>>(con, r);//Func<DataRow, bool> Expressionvar q = dt.AsEnumerable().Where(expLam.Compile()).Select(s => s);foreach (var row in q){dataGridView1.Rows[dt.Rows.IndexOf(row)].Selected = true;}}
       string[] SplitConditionStr(string Condition){string[] cons = new string[3];if (Condition.Contains("!=")){cons = Regex.Split(Condition, @"!=");return new string[] { cons[0].Replace("`", "").Replace("'", ""), @"!=", cons[1].Replace("`", "").Replace("'", "") };}else if (Condition.Contains(">=")){cons = Regex.Split(Condition, @">=");return new string[] { cons[0].Replace("`", "").Replace("'", ""), @">=", cons[1].Replace("`", "").Replace("'", "") };}else if (Condition.Contains("<=")){cons = Regex.Split(Condition, @"<=");return new string[] { cons[0].Replace("`", "").Replace("'", ""), @"<=", cons[1].Replace("`", "").Replace("'", "") };}else{char[] comparetors = new char[] { '=', '>', '<' };cons = Condition.Split(comparetors);if (Condition.Contains("=")){return new string[] { cons[0].Replace("`", "").Replace("'", ""), @"=", cons[1].Replace("`", "").Replace("'", "") };}else if (Condition.Contains(">")){return new string[] { cons[0].Replace("`", "").Replace("'", ""), @">", cons[1].Replace("`", "").Replace("'", "") };}else//(Condition.Contains("<")){return new string[] { cons[0].Replace("`", "").Replace("'", ""), @"<", cons[1].Replace("`", "").Replace("'", "") };}}}

DataRow.Field Expression [DataTable动态linq]相关推荐

  1. C# LINQ系列:LINQ to DataSet的DataTable操作 及 DataTable与Linq相互转换

    LINQ to DataSet需要使用System.Core.dll.System.Data.dll和System.Data.DataSetExtensions.dll,在项目中添加引用System. ...

  2. 模仿国外某小哥,做的一个字符串转动态linq表达式 及 部分扩展

    功能上还有部分的不足,目前还未能实现括号运算等 而且传入的字符串有一定的规则,至少对我个人来说已经是0 -> 1的过程 以下是代码: #region 动态linq帮助类,连接符号,运算符号 // ...

  3. Linq技术四:动态Linq技术 -- Linq.Expressions

    前面介绍了Linq的三个方面应用:Linq to SQL, Linq to XML和Linq to Object,这篇介绍一下动态Linq的实现方式及应用场景. 命名空间: System.Linq; ...

  4. .NET 现代化动态 LINQ 库 Gridify

    动态 LINQ 大家好,我是等天黑, 这次继续介绍开源项目,Gridify 是一个现代化动态 LINQ 库,它以最简单的方式将您的字符串转换为 LINQ 查询,并且有出色的性能.它还提供了一种使用基于 ...

  5. C# DataRow数组转换为DataTable

    public DataTable ToDataTable(DataRow[] rows) { if (rows == null || rows.Length == 0) return null; Da ...

  6. Flink报错 Cannot reference field by field expression on GenericType

    报错信息如下: Exception in thread "main" org.apache.flink.api.common.typeutils.CompositeType$Inv ...

  7. Linq to Sql : 动态构造Expression进行动态查询

    前一篇在介绍动态查询时,提到一个问题:如何根据用户的输入条件,动态构造这个过滤条件表达式呢? Expression<Func<ProductExt, bool>> predic ...

  8. 表达式计算 DataTable/DataRow/DataColumn Expression、JScript CodeDomProvider Eval

  9. Expression 表达式动态生成

    http://blog.csdn.net/duan1311/article/details/51769119 以上是拼装和调用GroupBy的方法,是不是很简单,只要传入分组列与合计列就OK了! 下面 ...

最新文章

  1. python中attr_python中hasattr()、getattr()、setattr()函数的使用
  2. opencv双目测距资料整理
  3. vue引入组件时‘@/xxxx’的意思
  4. IPV6地址校验(java)
  5. 为什么 JavaScript 的 this 要这么用?
  6. ssl提高组周六模拟赛【2018.9.22】
  7. Ubuntu 14.04 为root帐号开启SSH登录
  8. xss漏洞php注射实战,利用XSS渗透DISCUZ 6.1.0实战
  9. python colorama模块
  10. CVPR2021|引入记忆模块,突破长距离依赖视频预测的性能瓶颈
  11. ajax预加载html seo,AJAX网页如何实现SEO友好
  12. File.WriteAllText 写入TXT文件时不能正确换行只显示方块
  13. 【开发日志】gtest踩坑:-1: error: cannot find -llibgtest
  14. Python 之有趣的跑马灯
  15. ListView控件简单用法
  16. 花音机器人_【扑杀花音攻略组】超弩风机器人攻略(复刻x2)
  17. 【竞赛篇-竞赛定级及含“金”量】ABC类竞赛如何区分?哪些竞赛被认可?哪些竞赛不太被认可但“值”得参加?
  18. ESP32 开发笔记(四)LVGL控件学习 ColorPicker 颜色选择器控件
  19. 彻底解决微软EDGE浏览器新建标签页后出现Bing搜索框
  20. LeetCode第9题 回文数(Palindrome Number)

热门文章

  1. DepthFirstSearch BreadthFirstSearch
  2. 在中国当程序员,35岁是分水岭?这些新路你知道吗?
  3. Cobar Client的使用
  4. 量子十问之三:量子技术能将人“瞬间”转移到别的星球上吗?
  5. NRF52832官方SDK介绍
  6. 从功能上来看 多媒体计算机无法充当,2015中等职业学校计算机等级考试题库(含答案):多媒体题库.doc...
  7. Cocos creator 导入 tiled map地图资源,cocos 显示地图错乱偏移
  8. android中c文件怎么加logo,c – 如何在CMake中添加“-l”(ell)编译器标志
  9. dw如何把html转换成网址,我用flash做的网页,怎么把它在dw里变成html网页?
  10. synaptic No protocol specified issue