PetaPoco源代码学习--3.Sql类
PetaPoco对数据库的操作直接使用SQL语句,在代码中进行调用既可以直接传递SQL语句,也可以使用提供的SQL类来获取到SQL语句进行操作,直接传递SQL语句在内部实现中也是封装成Sql类传递到底层来操作的。Sql类实际上就是对SQL语句的一种封装,使你能够向操作类的方法一样来使用SQL语句。比如,
var sql=Sql.Builder.Select(“*”).From(“person”).Where(“ID=@”,””)
var sqlStr=sql.SQL;//select * from person where ID=’1345’;
Sql类采用函数式编程的思想,对SQL语句进行了抽象。当然,如果觉得这种表达方式不好,也可以直接传递SQL语句。
备注:使用Sql类时,如果传递参数,则在sql语句中@X进行占位,每次调用一个方法都从0开始,依次增加。
以下是对Sql类的详细描述:
/// <summary>
/// SQL语句类
/// </summary>
public class Sql
{
/// <summary>
/// 初始SQL语句
/// </summary>
private string mInitialSQL; /// <summary>
/// 初始SQL参数
/// </summary>
private object[] mInitialArgs; /// <summary>
/// 最终SQL语句
/// </summary>
private string mFinalSQL; /// <summary>
/// 最终SQL参数
/// </summary>
private object[] mFinalArgs; /// <summary>
/// right-hand-side 引用,理解为后继
/// </summary>
private Sql mRHS; /// <summary>
/// 获取实例
/// </summary>
public static Sql Builder
{
get { return new Sql(); }
} /// <summary>
/// 获取SQL语句
/// </summary>
public string SQL
{
get
{
Build();
return mFinalSQL;
}
} /// <summary>
/// 获取构建SQL语句的参数
/// </summary>
public object[] Arguments
{
get
{
Build();
return mFinalArgs;
}
} /// <summary>
/// 默认构造器
/// </summary>
public Sql()
{
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="args">SQL语句对应的参数</param>
public Sql(string sql, params object[] args)
{
mInitialSQL = sql;
mInitialArgs = args;
} private void Build()
{
//只需要构建一次即可
if (mFinalSQL != null)
return;
//根据SQL语句和参数构建最终语句
var sb = new StringBuilder();
var args = new List<object>();
Build(sb, args, null);
mFinalSQL = sb.ToString();
mFinalArgs = args.ToArray();
} /// <summary>
/// 向当前SQL实例添加后继SQL实例 Append another SQL builder instance to the right-hand-side of this SQL builder
/// </summary>
/// <param name="sql">后继SQL实例</param>
/// <returns>返回对象自身</returns>
public Sql Append(Sql sql)
{
//若当前对象包括后继对象,则向其后继对象添加后继对象
if (mRHS != null)
mRHS.Append(sql);
else
mRHS = sql;
mFinalSQL = null;
return this;
} /// <summary>
/// 向当前SQL实例添加SQL语句和对应参数
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="args">对应参数</param>
/// <returns>返回对象自身</returns>
public Sql Append(string sql, params object[] args)
{
return Append(new Sql(sql, args));
} /// <summary>
/// 判断SQL语句是否与参数表示类型相同
/// </summary>
/// <param name="sql">SQL帮助类</param>
/// <param name="sqltype">SQL类型</param>
/// <returns></returns>
private static bool Is(Sql sql, string sqltype)
{
return sql != null && sql.mInitialSQL != null && sql.mInitialSQL.StartsWith(sqltype, StringComparison.InvariantCultureIgnoreCase);
} /// <summary>
/// 构建SQL语句
/// </summary>
/// <param name="sb">StringBuilder保存Sql语句</param>
/// <param name="args">SQL参数</param>
/// <param name="lhs">SQL实例</param>
private void Build(StringBuilder sb, List<object> args, Sql lhs)
{
if (!string.IsNullOrEmpty(mInitialSQL))
{
if (sb.Length > )
{
sb.Append("\n");
}
var sql = ParametersHelper.ProcessParams(mInitialSQL, mInitialArgs, args);
//累加where条件
if (Is(lhs, "WHERE ") && Is(this, "WHERE "))
sql = "AND " + sql.Substring();
//累加Order by 条件
if (Is(lhs, "ORDER BY ") && Is(this, "ORDER BY "))
sql = ", " + sql.Substring();
//累加set语句
if (Is(lhs, "SET ") && Is(this, "SET "))
sql = ", " + sql.Substring(); sb.Append(sql);
}
//处理当前实例的后继实例(递归)
if (mRHS != null)
mRHS.Build(sb, args, this);
} /// <summary>
/// 向SQL实例添加set语句
/// </summary>
/// <param name="sql">update中的set语句,形如"{field} = {value}" </param>
/// <param name="args">可选参数</param>
/// <returns>当前SQL实例</returns>
public Sql Set(string sql, params object[] args)
{
return Append(new Sql("SET " + sql, args));
} /// <summary>
/// 向SQL实例添加where语句
/// </summary>
/// <param name="sql">where语句</param>
/// <param name="args">可选参数</param>
/// <returns>当前SQL实例</returns>
public Sql Where(string sql, params object[] args)
{
return Append(new Sql("WHERE (" + sql + ")", args));
} /// <summary>
/// 向SQL实例添加order by语句
/// </summary>
/// <param name="columns">待排序的列名称</param>
/// <returns>当前SQL实例</returns>
public Sql OrderBy(params object[] columns)
{
return Append(new Sql("ORDER BY " + string.Join(", ", (from x in columns select x.ToString()).ToArray())));
} /// <summary>
/// 向SQL实例添加select语句
/// </summary>
/// <param name="columns">查询的结果列名称</param>
/// <returns>当前SQL实例</returns>
public Sql Select(params object[] columns)
{
return Append(new Sql("SELECT " + string.Join(", ", (from x in columns select x.ToString()).ToArray())));
} /// <summary>
/// 向SQL实例添加查询表(多个表相互连接,数量指数级增长)
/// </summary>
/// <param name="tables">查询的表名称</param>
/// <returns>当前SQL实例</returns>
public Sql From(params object[] tables)
{
return Append(new Sql("FROM " + string.Join(", ", (from x in tables select x.ToString()).ToArray())));
} /// <summary>
/// 向SQL实例添加group by语句
/// </summary>
/// <param name="columns">待分组列名称</param>
/// <returns>当前SQL实例</returns>
public Sql GroupBy(params object[] columns)
{
return Append(new Sql("GROUP BY " + string.Join(", ", (from x in columns select x.ToString()).ToArray())));
} /// <summary>
/// 数据表连接
/// </summary>
/// <param name="joinType">连接类型</param>
/// <param name="table">待连接表名称</param>
/// <returns>SqlJoinClause实例</returns>
private SqlJoinClause Join(string joinType, string table)
{
return new SqlJoinClause(Append(new Sql(joinType + table)));
} /// <summary>
/// 数据表内连接
/// </summary>
/// <param name="table">待连接表名称</param>
/// <returns>SqlJoinClause实例</returns>
public SqlJoinClause InnerJoin(string table)
{
return Join("INNER JOIN ", table);
} /// <summary>
/// 数据表外连接
/// </summary>
/// <param name="table">待连接表名称</param>
/// <returns>SqlJoinClause实例</returns>
public SqlJoinClause LeftJoin(string table)
{
return Join("LEFT JOIN ", table);
} /// <summary>
/// 获取最终的SQL语句
/// </summary>
public override string ToString()
{
return SQL;
}
} /// <summary>
/// SQL连接语句
/// </summary>
public class SqlJoinClause
{
/// <summary>
/// 待连接的SQL对象
/// </summary>
private readonly Sql _sql; /// <summary>
/// 构造函数
/// </summary>
/// <param name="sql"></param>
public SqlJoinClause(Sql sql)
{
_sql = sql;
} /// <summary>
/// 向SQL对象添加表连接条件
/// </summary>
/// <param name="onClause">表连接条件</param>
/// <param name="args">可选参数</param>
/// <returns>SQL对象</returns>
public Sql On(string onClause, params object[] args)
{
return _sql.Append("ON " + onClause, args);
}
}
PetaPoco源代码学习--3.Sql类的更多相关文章
- PetaPoco源代码学习--0.目录贴
2017年3季度后,以人力外包的形式派驻到甲方单位进行项目救急时,接触到了甲方单位的ASP.NET MVC项目的ORM框架,它以PetaPoco(2012年的老版本)进行改造升级的,当初就想学习一下这 ...
- PetaPoco源代码学习--2.TableInfo、ColumnInfo类和Cache类
当把常用的特性填写到POCO实体类时,执行数据库操作时,需要根据实体类上的特性信息进行相应的操作,PetaPoco中的TableInfo和ColumnInfo类就是用来保存实体类上的特性信息. Tab ...
- PetaPoco源代码学习--1.使用的Attribute介绍
新版本的PetaPoco使用特性进行注解的形式来代替的老版本的映射类的形式.新版本中使用的特性主要包括以下几种: 名称 用途 TableNameAttribute Class 指定POCO实体类对 ...
- Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
- struts2源代码学习之初始化(一)
看struts2源代码已有一段时日,从今天開始,就做一个总结吧. 首先,先看看怎么调试struts2源代码吧,主要是下面步骤: 使用Myeclipse创建一个webproject 导入struts2须 ...
- 开源中国安卓client源代码学习(一) 渐变启动界面
开源中国安卓client源代码学习(一) 渐变启动界面 准备学习安卓开发, 看到网上有人推荐开源中国安卓client的源代码, 说里面包括了大部分技术, 于是准备好好研究研究. 特开通此系列博客来记录 ...
- 读Flask源代码学习Python--config原理
读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因 莫名其妙在第一份工作中使用了从来没有接 ...
- nginx源代码学习资源(不断更新)
nginx源代码学习是一个痛苦又快乐的过程,以下列出了一些nginx的学习资源. 首先要做的当然是下载一份nginx源代码,能够从nginx官方站点下载一份最新的. 看了nginx源代码,发现这是一份 ...
- djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习
Django REST framework JWT djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习 SECRET_KEY = '1)q(f8jrz^edwtr2 ...
随机推荐
- Java map的匿名类的初始化
可以直接使用: Map<String, Object> testMap = new HashMap<String, Object>() { { put("test1& ...
- AlexNet详解2
此处以caffe官方提供的AlexNet为例. 目录: 1.背景 2.框架介绍 3.步骤详细说明 5.参考文献 背景: AlexNet是在2012年被发表的一个金典之作,并在当年取得了ImageNet ...
- 一次典型的TFS故障处理:域控失联
问题描述 突然收到客户报告,开发人员登录TFS系统时,出现登录异常现象.即使输入了正确的账户和密码,TFS系统任然提示重新登录的页面,导致用户无法打开TFS系统. 即使登录成功,在修改代码或者修改工作 ...
- SoftWareHelper
SoftWareHelper 环境 Visual Studio 2017,.Net Framework 4.0 SDK GitHub源码:https://github.com/yanjinhuagoo ...
- C#知识点提炼期末复习专用
根据内部消息称:有三类题型: 程序阅读题:2题 简答题:2题 (主要是对概念的考查) 编程题:暂定2-3题 复习要点: .net framework 通用语言开发环境..NET基础类库..NET ...
- Android自定义组合控件详细示例 (附完整源码)
在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...
- [JavaScript] iframe更改了src后,父页面history.back只能后退iframe而不能使自己后退解决办法
浏览器的机制如此,在iframe导航变化后手动点击浏览器的后退按钮也依然只是后退iframe中的导航. 有一种解决方案是不要修改iframe.src,而是删除旧iframe元素,新建一个iframe元 ...
- 将python打包为.exe文件
第一步:在https://pypi.python.org/pypi/PyInstaller/2.1 下载pyinstaller. 第二步:解压缩,在该目录下命令行中执行python setup.py ...
- Go指南练习 rot13Reader
题目: 练习:rot13Reader 有种常见的模式是一个 io.Reader 包装另一个 io.Reader,然后通过某种方式修改其数据流. 例如,gzip.NewReader 函数接受一个 io. ...
- Vue2.5开发去哪儿网App 第四章笔记 上
一 . 组件细节知识点 1. 解决组件在h5中编码规范 例如 : table , ul , ol 等等 <table> <tbody> <row></r ...