本文介绍如何解析lambda表达式来获取一个满足条件的查询语句。

先看个截图 

通过设置实体对象Article_Content的查询表达式,就可以获取对应的参数化SQL语句,使用起来很方便,减少了代码的书写,同时提高了安全性。

本文需要了解的基础知识有:

  1. lambda表达式
  2. Expression表达式树
  3. 扩展方法

首先,我们应该有一个普通的实体对象和它的基类

//基类
class baseEntity
{internal Expression whereFunc;
}
//实体对象
class Article_Content : baseEntity
{public int? Article_Id { get; set; }public string Article_Title { get; set; }public string Article_SourceUrl { get; set; }
}

这个时候我们需要定义一些扩展方法以便对实体的查询表达式进行保存。我们的SQL语句的需求是要参数化的。所以,在实体对象这里还不知道数据库类型,没有办法获取对应的参数化符号。
/// <summary>
/// 设置匹配表达式
/// </summary>
public static void SetWhereFunc<T>(this T entity, Expression<Func<T, bool>> func) where T : baseEntity
{
entity.whereFunc = func;
}
好了。这个时候我们可以写出类似下面的代码了:
Article_Content art = new Article_Content();
art.SetWhereFunc(ar=>ar.Aritlce_Id == 4 && ar.Article_Title == "sss");

但是SQL语句中很常见的Like查询似乎还没有办法实现。
我们通过分析Where子句,发现where语句的做事然筛选出来的纪录要满足where子句的条件,那么where子句返回的就是一个bool,where子句其实是一个逻辑表达式。所以,就有了刚才SetWhereFunc函数里面的第二个参数中Func的返回值是bool。
既然where子句要求返回的是一个bool表达式同理:Like、In、Not等表达方法我们也只能让它返回的是bool值;
那么就有了下面的扩展函数:
public static bool In<T>(this T obj, T[] array)
{return true;
}
public static bool Like(this string str, string likeStr)
{return true;
}

这个时候很现在,我们的SetWhereFunc可以写出如下的代码了:

art.SetWhereFunc(ar=>ar.Aritlce_Id.In(new int?[]{4,6}) && ar.Article_Title.Like("%sss"));
到目前为止,前台编写方式已经解决了。
剩下的就是如何来分析我们设置的这个lambda表达式了。
当然分析lambda表达式的时候,我们还需要考虑生成的SQL语句的参数化。这个时候还需要另一个数据操作对象:
public abstract class DbOperate
{/// <summary>/// 获取此数据类型的参数形式表现/// </summary>/// <param name="fieldsName"></param>/// <returns></returns>public abstract string GetParamFlag(string fieldsName);//其他操作方法.....
}

这个对象还有其他方法,不过在这里,我们主要使用的就是这样一个参数标识,如果它在MSSQL里,它返回的是@+fieldName,Orcale则返回的是:fieldName。
在构建SQL语句的时候,我们同样也使用扩展方法来解析表达式。
internal static string Where<T>(this T entity, Expression func, DbOperate dbop, ref ArrayList alParamNames, ref ArrayList alParamValues) where T : baseEntity
{return ExpressionRouter(func, dbop, ref alParamNames, ref alParamValues);
} 

lambda表达式也是表达式的一种。那么我们可以通过分析表达式的类型计算对应的产生式。
现在主要遇到的表达式有以下几种:

  1. BinaryExpression
  2. LambdaExpression
  3. MethodCallExpression
  4. MemberExpression
  5. ConstantExpression
  6. NewArrayExpression
  7. UnaryExpression

根据不同的类型,可以进行不同操作,为了简单起见,我们这里演示的是直接拼接字符串的方式,各位可以自己尝试使用参数的方式,函数原型在上面了。

static string BinarExpressionProvider(Expression left, Expression right, ExpressionType type){string sb = "(";//先处理左边sb += ExpressionRouter(left);sb += ExpressionTypeCast(type);//再处理右边string tmpStr = ExpressionRouter(right);if (tmpStr == "null"){if (sb.EndsWith(" ="))sb = sb.Substring(0, sb.Length - 2) + " is null";else if (sb.EndsWith("<>"))sb = sb.Substring(0, sb.Length - 2) + " is not null";}elsesb += tmpStr;return sb += ")";}//表达式路由计算 static string ExpressionRouter(Expression exp){string sb = string.Empty;if (exp is BinaryExpression){BinaryExpression be = ((BinaryExpression)exp);return BinarExpressionProvider(be.Left, be.Right, be.NodeType);}else if (exp is MemberExpression){MemberExpression me = ((MemberExpression)exp);return me.Member.Name;}else if (exp is NewArrayExpression){NewArrayExpression ae = ((NewArrayExpression)exp);StringBuilder tmpstr = new StringBuilder();foreach (Expression ex in ae.Expressions){tmpstr.Append(ExpressionRouter(ex));tmpstr.Append(",");}return tmpstr.ToString(0, tmpstr.Length - 1);}else if (exp is MethodCallExpression){MethodCallExpression mce = (MethodCallExpression)exp;if (mce.Method.Name == "Like")return string.Format("({0} like {1})", ExpressionRouter(mce.Arguments[0]), ExpressionRouter(mce.Arguments[1]));else if (mce.Method.Name == "NotLike")return string.Format("({0} Not like {1})", ExpressionRouter(mce.Arguments[0]), ExpressionRouter(mce.Arguments[1]));else if (mce.Method.Name == "In")return string.Format("{0} In ({1})", ExpressionRouter(mce.Arguments[0]), ExpressionRouter(mce.Arguments[1]));else if (mce.Method.Name == "NotIn")return string.Format("{0} Not In ({1})", ExpressionRouter(mce.Arguments[0]), ExpressionRouter(mce.Arguments[1]));}else if (exp is ConstantExpression){ConstantExpression ce = ((ConstantExpression)exp);if (ce.Value == null)return "null";else if (ce.Value is ValueType)return ce.Value.ToString();else if (ce.Value is string || ce.Value is DateTime || ce.Value is char)return string.Format("'{0}'", ce.Value.ToString());}else if (exp is UnaryExpression){UnaryExpression ue = ((UnaryExpression)exp);return ExpressionRouter(ue.Operand);}return null;}static string ExpressionTypeCast(ExpressionType type){switch (type){case ExpressionType.And:case ExpressionType.AndAlso:return " AND ";case ExpressionType.Equal:return " =";case ExpressionType.GreaterThan:return " >";case ExpressionType.GreaterThanOrEqual:return ">=";case ExpressionType.LessThan:return "<";case ExpressionType.LessThanOrEqual:return "<=";case ExpressionType.NotEqual:return "<>";case ExpressionType.Or:case ExpressionType.OrElse:return " Or ";case ExpressionType.Add:case ExpressionType.AddChecked:return "+";case ExpressionType.Subtract:case ExpressionType.SubtractChecked:return "-";case ExpressionType.Divide:return "/";case ExpressionType.Multiply:case ExpressionType.MultiplyChecked:return "*";default:return null;}}

  

到这里,一个基于表达式分析的实体查询就做好了。

下面是文章一开始的那个lambda表达式分析出来的对应的where语句

对应的参数和参数值顺序是一一对应的。

我这里的对Expression表达式进行了计算,所以最后一个参数对应的

string.Concat(GetStr(7), "sdfsdf".Length, "sssss" + GetStr(6)).ToUpper()

这个表达式已经被计算完成得到"GOOD76SSSSSGOOD6",GetStr(int)函数见第一张截图。

这里主要体会的是用Expression Tree的一个实际用法。实际跑起来体会下就能明白。要说的话实在内容太多。而前面的都介绍都是概念性的.

代码下载地址:http://download.csdn.net/detail/ysq5202121/4263117

转载于:https://www.cnblogs.com/ysq5202121/p/3419590.html

用lambda构建ORM查询语句相关推荐

  1. es ik 多字段查询_SpringBoot使用注解的方式构建Elasticsearch查询语句,实现多条件的复杂查询...

    背景&痛点 通过ES进行查询,如果需要新增查询条件,则每次都需要进行硬编码,然后实现对应的查询功能.这样不仅开发工作量大,而且如果有多个不同的索引对象需要进行同样的查询,则需要开发多次,代码复 ...

  2. R语言构建仿真数据库(sqlite)并使用dplyr语法和SQL语法查询数据库、将dplyr语法查询语句翻译为SQL查询语句

    R语言构建仿真数据库(sqlite)并使用dplyr语法和SQL语法查询数据库.将dplyr语法查询语句翻译为SQL查询语句 目录

  3. EFCore查询语句生成流程、让EFCore支持批量Update/Delete/MergeInto

    引子 之前发现了一款叫 EFCore.BulkExtensions 的 nuget 包.里面提供了大量的 BulkInsertOrUpdateOrDelete 和 BatchUpdate 的拓展,可以 ...

  4. 知识图谱入门2-2:用户输入->知识库的查询语句

    注:欢迎关注datawhale:https://datawhale.club/ 系列: 知识图谱入门一:知识图谱介绍 知识图谱入门2-1:实践--基于医疗知识图谱的问答系统 知识图谱入门2-2:用户输 ...

  5. Task 4 用户输入->知识库的查询语句

    Task 4 用户输入->知识库的查询语句 引言 本部分任务主要是将用户输入问答系统的自然语言转化成知识库的查询语句,因此本文将分成两部分进行介绍. 第一部分介绍任务所涉及的背景知识; 第二部分 ...

  6. 达芬奇 - 构建数据查询API的框架

    达芬奇 - 基于"Serverless"的数据查询API框架 此文背景 我们要解决什么样的问题? 系统要求 系统设计 访问控制列表及其使用 过滤器以及其语法 Serverless ...

  7. Datawhale 知识图谱组队学习 之 Task 4 用户输入->知识库的查询语句

    文章编写人:王翔 特别鸣谢:QASystemOnMedicalGraph 目录 Datawhale 知识图谱组队学习 之 Task 4 用户输入->知识库的查询语句 目录 一.引言 二.什么是问 ...

  8. Datawhale 知识图谱组队学习之Task 4 用户输入->知识库的查询语句

    Datawhale 知识图谱组队学习 之 Task 4 用户输入->知识库的查询语句 文章编写人:王翔 github 地址: 特别鸣谢:QASystemOnMedicalGraph 目录 Dat ...

  9. python django orm查询集总结

    1 .什么是ORM (Object Relational Mapping ) 它的作用是在关系型数据库和业务实体对象做一个映射,我们在操作具体业务对象的时候就可以省去了和SQL语句打交道,只需要简单的 ...

最新文章

  1. 关于CSS的长度单位及颜色表示
  2. 数据蒋堂 | 大数据技术的4个E
  3. sql优化的方法及思路_微生物发酵 技术优化思路 与方法
  4. 解决Win10不能访问共享文件夹的问题
  5. OpenCV Laplace point/edge detection拉普拉斯点/边缘检测的实例(附完整代码)
  6. 使用轮转算法求时间片_彩票调度算法,让进程们拼手气? --当操作系统遇上随机算法...
  7. 编写程序,使用指针把一个 int 型数组的所有元素设置4.18: 为 0。
  8. python爬虫beautifulsoup_python爬虫初步之BeautifulSoup实战
  9. erlang 编译之 to_core
  10. Git 合并分支选项 --squash 合并提交历史
  11. BZOJ2809-左偏树合并
  12. [转载] linux cgroup
  13. AttackerKB:免费的众筹漏洞评估知识库
  14. ios时间相差多少天_iOS 时间戳和时间互换,计算两日期相隔天数
  15. ARG MIN的含义是什么?
  16. 小米球ngrok如何后台启动
  17. 计算机工程师难度排名,【2018一级造价工程师考试各个科目的难度排行榜】- 环球网校...
  18. antdvue 表格插入自定义行
  19. “萌新”商家应该如何选择电商直播平台呢?
  20. java servlet继承_servlet继承什么类

热门文章

  1. 网工路由基础(3)RIP原理与配置
  2. 有一种惨:人还在,数据没了...
  3. 超实用!VLAN、TRUNK、VLAN间路由基础
  4. OpenKruise v0.8.0 核心能力解读:管理 Sidecar 容器的利器
  5. 无责任畅想:云原生中间件的下一站
  6. ChaosBlade 在工商银行混沌工程体系中的应用实践
  7. 2020 年国内 Serverless 用户规模:阿里云占比第一,达 66%
  8. 阿里云叔同:以容器为代表的云原生技术,已经成为释放云价值的最短路径
  9. 快速部署 Spring PetClinic 到函数计算平台
  10. xpath元素和css选择器的定位