使用操作符重载,生成ORM实体类的SQL条件语句
ORM框架的一个不可或缺的功能就是根据实体类,生成操作数据库的SQL语句,这其中,最难处理的就是那些复杂的SQL条件比较语句。比如,有下面这样一个SQL语句:
SELECT [id],[BankCode],[CityCode],[FundCode],[FundName],[FundReviews],[EndDagte],[addDate]
FROM [FundReviews]
WHERE (
([CityCode]=@CP1 OR [BankCode]=@CP2)
AND ([FundCode]=@CP3 OR [BankCode]=@CP4)
)
这个复杂的查询条件由两个OR子条件最后组合成一个AND 条件的,因此它有3组条件:
1:[CityCode]=@CP1 OR [BankCode]=@CP2;
2:[FundCode]=@CP3 OR [BankCode]=@CP4;
3:1 AND 2 ;
而条件1其实就是 Condition1 OR Condition2,这又是一个条件组合。
我们发现,尽管SQL的条件语句可能很复杂,但这些条件却是由一些子条件组合成的,或者说由一组条件组合成一个新的条件,大家想想,这是不是典型的“组合模式”阿?
在PDF.NET框架的ORM组件中,有一个专门处理条件的对象OQLCompare ,它就是根据“组合模式”设计的,我们来看看怎么由它来构造这个查询条件:
1,采用AND,OR重载:
FundReviews p = new FundReviews();//实例化一个实体类
OQL q = new OQL(p); //实例化一个OQL对象
Console.WriteLine("OQLCompare 复杂比较条件表达式测试---------");
OQLCompare cmp = new OQLCompare(p);
OQLCompare cmpResult = (cmp.Comparer(p.CityCode, OQLCompare.CompareType.Equal, "021")
| cmp.Comparer(p.BankCode, OQLCompare.CompareType.Equal, "008"))
& (cmp.Comparer(p.FundCode, OQLCompare.CompareType.Equal, "KF008")
| cmp.Comparer(p.BankCode, OQLCompare.CompareType.Equal, "008"));
q.Select().Where(cmpResult);
Console.WriteLine("SQL=" + q.ToString());
在OQL中,采用了类似SQL的语法,也是
Select([属性列表]).Where([条件表达式]).OrderBy([排序字段]).GroupBy([分组字段])
其中[条件表达式]就可以使用OQLCompare对象来构造。由于OQLCompare对象Comparer函数返回的仍然是一个OQLCompare对象,所以可以利用这个特点,采用组合模式,构造出非常复杂的SQL条件语句。
我们看到OQL采用了类似函数式的语法风格,但在[条件表达式]的构造过程中,还是显得很冗长,我们可以继续对OQLCompare对象进行重构:
/// <summary>
/// 设置等于某个实体属性的比较条件
/// </summary>
/// <param name="compare">当前实体比较对象</param>
/// <param name="Value">要比较的值</param>
/// <returns>构造的实体比较对象</returns>
public static OQLCompare operator ==(OQLCompare compare, object Value)
{
return BuildOperator(compare, Value, " = ");
}
/// <summary>
/// 设置不等于某个实体属性的比较条件
/// </summary>
/// <param name="compare">当前实体比较对象</param>
/// <param name="Value">要比较的值</param>
/// <returns>构造的实体比较对象</returns>
public static OQLCompare operator !=(OQLCompare compare, object Value)
{
return BuildOperator(compare, Value, " <> ");
}
/// <summary>
/// 根据实体对象的属性,获取新的条件比较对象
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
public OQLCompare Property(object field)
{
OQLCompare cmp = new OQLCompare();
cmp.CompareString = this.currPropName ;
return cmp;
}
private static OQLCompare BuildOperator(OQLCompare compare, object Value,string operatorString)
{
string paraName = compare.GetNewParameterName();
compare.CompareString += operatorString + paraName;
compare.compareValueList.Add(paraName.Substring(1), Value);
return compare;
}
我们可以采用类似的方式,继续实现 >=,>,<=,< 等SQL条件比较符号的重载,这里就不一一举例了,我们来看新的使用方式:
2,采用SQL比较符号的重载:
//对象 p 为实体类
OQLCompare cmp2 = new OQLCompare(p);
OQLCompare cmpResult2 =
( cmp2.Property(p.CityCode) == "021" | cmp2.Property(p.BankCode) == "008")
&
( cmp2.Property(p.FundCode) == "KF008"| cmp2.Property(p.BankCode) == "008");
q.ReSet();//重新初始化OQL
q.Select().Where(cmpResult2);
Console.WriteLine("操作符重载 SQL=" + q.ToString());
现在这个SQL条件的构造过程是不是清晰多了?这就是操作符重载的魅力:)
3,使用Equal方法,简化相等比较
直接看下面的代码,功能跟上面的例子一样:
//对象 p 为实体类
OQLCompare cmp2 = new OQLCompare(p);
OQLCompare cmpResult2 =
( cmp2.Equal(p.CityCode,"021") | cmp2.Equal(p.BankCode,"008") )
&
( cmp2.Equal(p.FundCode,"KF008") | cmp2.Equal(p.BankCode,"008") );
q.ReSet();//重新初始化OQL
q.Select().Where(cmpResult2);
Console.WriteLine("操作符重载 SQL=" + q.ToString());
从性能上来说,这种方式效率稍高,因为它是函数式的处理方式,更直接。
-------------------------------------------------------------------------
注:本文介绍的这个OQL特性仅在PDF.NET Ver 4.3版本受支持,但之前的版本参照本文说的方法加以改进,也可以使用。有关PDF.NET的版本信息,请看官网介绍: http://www.pwmis.com/sqlmap 有关PDF.NET的开源信息,请参看我的博客文章:
节前送礼:PDF.NET(PWMIS数据开发框架)V3.0版开源
- Java 四种线程池的使用
- 搭建 Jenkins-2.83 服务,部署 spring boot 项目
- Spring Boot 中使用 Java API 调用 lucene
- Spring Boot 中使用 Java API 调用 Elasticsearch
- Spring Boot 中使用 公共配置
- WebView 和 JS 交互,如何将 Java 对象和 List 传值给 JS ?
- Spring Boot 中使用 LogBack 配置
- Spring Boot 中使用 RabbitMQ
- 手把手教你dubbo怎么用?
- 一步一步实现Android的MVP框架
- Base封装之我的最简MVP架构
- 请求跨域的解决方案
- 运用Kubernetes进行分布式负载测试
- Spring Cloud(五)断路器监控(Hystrix Dashboard)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 最全Kafka 设计与原理详解【2017.9全新】
- 【数学建模】模拟退火算法介绍及实现
- Proxy系统架构升级
- Kafka快速上手(2017.9官方翻译)
- 【动手学深度学习笔记】之Pytorch实现线性回归
- 【动手学深度学习笔记】之softmax回归
- 一文全面梳理各种锁机制
- 【动手学深度学习笔记】之图像分类数据集(Fashion-MNIST)
- 探讨缓存行与伪共享
- Stream 流解读
- 3 分钟生成一个单元测试报告,这个样式爱了
- 使用pymouse模块时候报错No module named 'windows'
- GO用内置包写爬虫
- rsyslog详解实战和避坑
- 删除行对MySQL序列有这么多影响?