用lambda构建ORM查询语句
本文介绍如何解析lambda表达式来获取一个满足条件的查询语句。
先看个截图 ![]()
通过设置实体对象Article_Content的查询表达式,就可以获取对应的参数化SQL语句,使用起来很方便,减少了代码的书写,同时提高了安全性。
本文需要了解的基础知识有:
- lambda表达式
- Expression表达式树
- 扩展方法
首先,我们应该有一个普通的实体对象和它的基类
//基类
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; }
}
/// <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");
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);
//其他操作方法.....
}
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表达式也是表达式的一种。那么我们可以通过分析表达式的类型计算对应的产生式。
现在主要遇到的表达式有以下几种:
- BinaryExpression
- LambdaExpression
- MethodCallExpression
- MemberExpression
- ConstantExpression
- NewArrayExpression
- 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";
}
else
sb += 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
用lambda构建ORM查询语句的更多相关文章
- hisql ORM 查询语句使用教程
HiSql 提供一个可以适合多种数据库的中间查询语法,不需要关注各个数据库的语法特性,通过HiSql写语句可以在常用的不同类型数据库中执行,且语法与Sql语境类似一看就懂一学就会 hisql.net ...
- SpringBoot使用注解的方式构建Elasticsearch查询语句,实现多条件的复杂查询
背景&痛点 通过ES进行查询,如果需要新增查询条件,则每次都需要进行硬编码,然后实现对应的查询功能.这样不仅开发工作量大,而且如果有多个不同的索引对象需要进行同样的查询,则需要开发多次,代码复 ...
- ORM查询条件
模板: from django.db import models class Article(models.Model): title = models.CharField(max_length=20 ...
- Django(17)orm查询操作
前言 查找是数据库操作中一个非常重要的技术.查询一般就是使用filter.exclude以及get三个方法来实现.我们可以在调用这些方法的时候传递不同的参数来实现查询需求.在ORM层面,这些查询条件都 ...
- ORM开发之解析lambda实现group查询(附测试例子)
目的:以编程方式实现group查询,在开发ORM时,需要达到这样的效果 先看一个简单的group语句 select BarCode,ProductName,COUNT(BarCode) as tota ...
- ORM开发之解析lambda实现完整查询(附测试例子)
上次讲解了怎么解析匿名对象(ORM开发之解析lambda实现group查询),这次来实现解析二元运算,完成基本条件语法 先看一个表达式 query.Where(b => b.Number == ...
- 浅谈sql 、linq、lambda 查询语句的区别
浅谈sql .linq.lambda 查询语句的区别 LINQ的书写格式如下: from 临时变量 in 集合对象或数据库对象 where 条件表达式 [order by条件] select 临时变量 ...
- 第二十篇ORM查询与SQL语句
ORM查询与SQL语句 多表操作 创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情 ...
- Lambda表达式转SQL语句类库
/* 作者:道法自然 * 个人邮件:myyangbin@sina.cn * 2014-10-1 */ Lambda表达式转SQL语句类库源码下载:http://download.csdn.net/ ...
随机推荐
- 实时动态更新曲线图,x轴时间s随数据的变化而变化
$(function () { $(document).ready(function () { Highcharts.setOptions({ global: ...
- hadoop 存储空间满了
-- ::, WARN mapred.LocalJobRunner - job_local_0001 org.apache.hadoop.util.DiskChecker$DiskErrorExcep ...
- Hadoop集群(第5期副刊)_JDK和SSH无密码配置
1.Linux配置java环境变量 1.1 原文出处 地址:http://blog.csdn.net/jiedushi/article/details/6672894 1.2 解压安装jdk 在she ...
- JavaScript 按回车键提交搜索表单 easyui ajax方式
<!-- 搜索框 --> <form id="bUserSearchForm" style="padding:8px;" onkeydown= ...
- [状压dp]HDU3001 Travelling
题意: 走n个城市, m条路, 起点任意, 每个城市走不超过两次, 求最小花费, 不能走输出-1. $1\le n\le 10$ 分析: 每个城市的拜访次数为0 1 2, 所以三进制状压, 先预处理1 ...
- UVA 10896 Sending Email
这个题目真是伤透脑筋了,一直RE,连着改了好几个版本,又是spfa,又是单调队列dijkstra+单调队列,总是不过,后来发现M开小了,双向边应该开m的两倍,悲剧啊!!!以后不管怎样,数组一定要尽量开 ...
- !!Python字典增删操作技巧简述+Python字典嵌套字典与排序
http://developer.51cto.com/art/201003/186006.htm Python编程语言是一款比较容易学习的计算机通用型语言.对于初学者来说,首先需要掌握的就是其中的一些 ...
- S3C2410 实验三——跑马灯实验
http://www.evernote.com/shard/s307/sh/f2a748e7-34c4-4ce6-acac-82a756cc9e82/ad5813188d655e504857970db ...
- RPGJS 进阶分析之 如何使用RMXP导出的数据
首先启动RMXP 在主脚本编辑区粘贴官方提供的导出数据脚本. 之后启动并进入游戏之后按F8键就可以调出导出Map和Animation的菜单 导出后的数据保存在工程目录下的RpgJs目录下. Datab ...
- Sum of Digits / Digital Root
Sum of Digits / Digital Root In this kata, you must create a digital root function. A digital root i ...