DbUtility Ex
扩展 DbUtility (1)
2014-05-22 21:48 by Ivony..., 234 阅读, 3 评论, 收藏, 编辑
本文原始路径: https://www.zybuluo.com/Ivony/note/14074
前言
DbUtility v3 是一个开源的轻量级数据库访问框架,源代码通过 Apache 协议发布,可以用于商业用途。最新的版本可以通过 NuGet 进行下载,项目及源代码下载地址:
https://github.com/Ivony/DbUtility
DbUtility 第一个版本公开于七年前,关于 DbUtility 的历史和 DbUtility 的使用,请参考下面这篇博客:
http://www.cnblogs.com/Ivony/p/3659746.html
https://www.zybuluo.com/Ivony/note/8277
作为一个开源项目,DbUtility 不仅仅致力于帮助大家简化数据库访问,也非常欢迎和期待大家的共同参与,不论是提交 Bug 或者单元测试,或是新的特性需求,以及自己动手为 DbUtility 增加更多有趣的功能,都是参与开源项目的方式。这篇文章面向所有有志于为 DbUtility 增添自定义功能的程序员,介绍 DbUtility 的扩展架构。
基本结构
DbUtility v3 相较于之前版本的最大区别,也是 DbUtility v3 傲视其他轻量级数据库访问框架的地方,就是其优良的扩展架构。正如之前的介绍所述,DbUtility 将一个数据库查询分为三个部分:
- 查询执行器
- 查询构建器
- 结果构建器
这三个部分各有一个关键的接口,分别为:
- IDbExecutor where T : IDbQuery 定义某种类型查询的查询执行器。
- IDbQuery 定义特定的数据库查询
- IDbExecuteContext 定义数据库查询执行上下文,其中包括 DataReader 对象。
譬如说 SqlDbUtility 类型便是面向 SQL Server 数据库的查询执行器实现类型,其声明为:
public class SqlDbUtility :
IAsyncDbExecutor<ParameterizedQuery>,
IAsyncDbExecutor<StoredProcedureQuery>,
IDbTransactionProvider<SqlDbUtility>
IAsyncDbExecutor 是 IDbExecutor 的异步版本,表示可以异步执行指定类型的查询。可以看出来SqlDbUtility实现了两个查询执行器接口,分别是 IAsyncDbExecutor<ParameterizedQuery> 和 IAsyncDbExecutor<StoredProcedureQuery> 这表示这个类型的对象既可以执行 ParameterizedQuery 类型(参数化查询)的查询,也能执行 StoredProcedureQuery 类型(存储过程)的查询。
扩展查询构建器
接下来我们尝试扩展一个查询构建方法,就像T( "SELECT * FROM Users" )一样。
假定我们经常会遇到一个场景,需要获取某个表的所有数据,如果直接使用T来构建参数化查询,则所需写的SQL语句很多: SELECT * FROM TableName ,我们希望简化为 DT( "TableName" ) 的形式,该如何做呢?
首先我们要确定我们是否需要构建一种新的查询类型,因为构建新的查询类型,需要同时修改查询执行器,在本例中暂不涉及这么深入的问题。我们假定暂且借用参数化查询对象,只是简化其生成代码。
那么首先我们需要了解的一个事实是,所有的查询构建方法其实都是扩展方法,针对特定的查询执行器,对其进行扩展。如果我们生成的是一个参数化查询,那么我们需要一个参数化查询执行器才能执行,所以我们要针对参数化查询执行器进行扩展。首先新建一个扩展方法所需的静态类型:
public static class MyExtensions
{ }
值得注意的是定义扩展方法的类型必须是静态类型。
然后我们添加一个扩展方法,因为我们最终生成的查询类型是参数化查询,所以我们需要对可以执行参数化查询的对象进行扩展,像这样:
public static void DT( this IDbExecutor<ParameterizedQuery> executor, string tableName )
{
throw new NotImplementedException();
}
请注意我这边的返回值类型还没有填写,因为这里涉及到另一个问题,单纯的查询对象是不能被执行的,为了达到 db.DT( "Users" ).ExecuteDataTable() 这样的效果,我们需要把查询对象和查询执行器捆绑起来,这个捆绑后的对象的类型为 IDbExecutableQuery (意为可执行的查询),所以我们需要把返回值设置为 IDbExecutableQuery 类型:
public static IDbExecutableQuery DT( this IDbExecutor<ParameterizedQuery> executor, string tableName )
{
throw new NotImplementedException();
}
DbUtility 已经为我们提供了现成的 IDbExecutableQuery 的实现,即 DbExecutableQuery<T> 类型,我们只需要构建一个查询对象,再连同查询执行器一起调用这个类型的构造函数即可:
public static IDbExecutableQuery DT( this IDbExecutor<ParameterizedQuery> executor, string tableName )
{
ParameterizedQuery query = null;
return new DbExecutableQuery<ParameterizedQuery>( executor, query );
}
最后,我们需要构建一个参数化查询对象,参数化查询对象作为基础查询对象,有很多种方式来构建,最常见的就是利用模板来构建,如果直接调用 db.T 方法,事实上构建出来的是 DbExecutableQuery<ParameterizedQuery> 类型的对象,好在系统提供了一个静态类型 Db 来对这些常见任务提供支持:
public static IDbExecutableQuery DT( this IDbExecutor<ParameterizedQuery> executor, string tableName )
{
ParameterizedQuery query = Db.T( "SELECT * FROM " + tableName );
return new DbExecutableQuery<ParameterizedQuery>( executor, query );
}
至此,我们的第一个扩展就已经完成了,马上来试一下:
var db = SqlDbUtility.Create( "Database" );
var data = db.DT( "Users" ).ExecuteDataTable();
尾声
事实上你知道吗,db.T 这个方法,其内部实现就是这样的
以下摘自DbUtility v3源代码:

public static DbExecutableQuery<ParameterizedQuery> Template( this IDbExecutor<ParameterizedQuery> executor, string template, params object[] parameters )
{
return new DbExecutableQuery<ParameterizedQuery>( executor, TemplateParser.ParseTemplate( template, parameters ) );
}
public static DbExecutableQuery<ParameterizedQuery> T( this IDbExecutor<ParameterizedQuery> executor, string template, params object[] parameters )
{
return Template( executor, template, parameters );
}

接下来,我们把这个方法再进一步扩展,我们希望用户调用这个方法的时候,不再返回一个可执行的查询对象,而是直接执行查询,并将 DataTable 返回就好了,相信聪明的你应该很快就能想到怎样写了:

public static class MyExtensions
{
public static DataTable DT( this IDbExecutor<ParameterizedQuery> executor, string tableName )
{
ParameterizedQuery query = Db.T( "SELECT * FROM " + tableName );
return new DbExecutableQuery<ParameterizedQuery>( executor, query ).ExecuteDataTable();
}
}

没错,借助优秀的可扩展架构,DbUtility可以被任意改造为任何你所喜欢 API 的形式,这种逆天的扩展性,是深深的植入在 DbUtility 整体架构模型设计中的。构成了 DbUtility 无与伦比的体验。
随笔分类 -C#
扩展 DbUtility (1)
2014-05-22 21:48 by Ivony..., 237 visits, 网摘, 收藏, 编辑
Jumony Core 3,真正的HTML引擎,正式版发布
2013-11-28 17:22 by Ivony..., 6556 visits, 网摘, 收藏, 编辑
新项目,WebTest
2013-11-02 13:28 by Ivony..., 599 visits, 网摘, 收藏, 编辑
Jumony Core 2.2 发布
2012-12-20 12:50 by Ivony..., 1926 visits, 网摘, 收藏, 编辑
C#5纯属YY的展望
2011-05-23 23:27 by Ivony..., 2894 visits, 网摘, 收藏, 编辑
Jumony入门(四)无缝体验
2010-12-24 00:39 by Ivony..., 3340 visits, 网摘, 收藏, 编辑
Jumony入门(三)初探解析器
2010-12-22 01:28 by Ivony..., 4437 visits, 网摘, 收藏, 编辑
Jumony入门(二)初识选择器
2010-12-20 17:05 by Ivony..., 3683 visits, 网摘, 收藏, 编辑
DbUtility Ex的更多相关文章
- 扩展 DbUtility (1)
本文原始路径: https://www.zybuluo.com/Ivony/note/14074 前言 DbUtility v3 是一个开源的轻量级数据库访问框架,源代码通过 Apache 协议发布, ...
- DbUtility v3 背后的故事
DbUtility v3 背后的故事 时间 DbUtility v3构思了差不多大半年,真正开发到第一个版本发布到NuGet却只花了50天.中途大量时间在完善 Jumony 3,只有三周来开发DbUt ...
- DbUtility v3
DbUtility v3 历史 七年前,也就是2007年,我在博客园写了一篇博文,开源并发布了恐怕是我第一个开源项目,DbUtility.其设计的初衷就是为了简化ADO.NET繁琐的数据库访问过程,提 ...
- ASP.NET中常用的几个李天平开源公共类LTP.Common,Maticsoft.DBUtility,LtpPageControl
ASP.NET中常用的几个开源公共类: LTP.Common.dll: 通用函数类库 源码下载Maticsoft.DBUtility.dll 数据访问类库组件 源码下载LtpPageC ...
- ASP.NET中常用的几个李天平开源公共类LTP.Common,Maticsoft.DBUtility,LtpPageControl (转)
ASP.NET中常用的几个开源公共类: LTP.Common.dll: 通用函数类库 源码下载Maticsoft.DBUtility.dll 数据访问类库组件 源码下载LtpPageC ...
- “DBUtility.DbHelperSQL”的类型初始值设定项引发异常 “DBUtility.DbHelperSQL”的类型初始值设定项引发异常
今天遇到了一个这样的问题“DBUtility.DbHelperSQL”的类型初始值设定项引发异常“DBUtility.DbHelperSQL”的类型初始值设定项引发异常 也许有和我遇到这问题的人也在这 ...
- JDBC实例--工具类升级,使用Apache DBCP连接池重构DBUtility,让连接数据库更有效,更安全
直接使用JDBC访问数据库时,需要避免以下隐患: 1. 每一次数据操作请求都需要建立数据库连接.打开连接.存取数据和关闭连接等步骤.而建立和打开数据库连接是一件既耗资源又费时的过程,如果频繁发生这种数 ...
- c# 数据库通用类DbUtility
DbProviderType数据库类型枚举 /// <summary> /// 数据库类型枚举 /// </summary> public enum DbProviderTyp ...
- 用SqlBulkCopy批量安插数据时提示来自数据源的 String 类型的给定值不能转换为指定目标列的类型 int
dr["description"] = ds.Tables[0].Rows[i]["组织描述"].ToString(); dr[& ...
随机推荐
- i++与++i哪个效率更高
简单的比较前缀自增运算符和后缀自增运算符的效率是片面的, 因为存在很多因素影响这个问题的答案. 首先考虑内建数据类型的情况: 如果自增运算表达式的结果没有被使用, 而是仅仅简单地用于增加一元操作数, ...
- Java 反射 想
所谓反射.是指在执行时状态中,获取类中的属性和方法.以及调用当中的方法的一种机制. 这样的机制的作用在于获取执行时才知道的类(Class)及当中的属性(Field).方法(Method)以及调用当中的 ...
- 2014ACM/ICPC亚洲区域赛牡丹江站汇总
球队内线我也总水平,这所学校得到了前所未有的8地方,因为只有两个少年队.因此,我们13并且可以被分配到的地方,因为13和非常大的数目.据领队谁oj在之上a谁去让更多的冠军.我和tyh,sxk,doub ...
- JSP具体条款——response对象
response对象 response为响应对象client要求.输出信息到客户.他封装JSP反应生成.发送client在回应client要求. 1.重定向网页 使用response对象的sendRe ...
- XCL-Charts绘画面积图(AreaChart) 案件1
样本区域地图,发现区域图的时候把做向上注视位置图更具优势的管理. 在改变. 区域图网格和轴是不一样的处理与其它图, 它是用来表示其影响范围的覆盖范围,车桥无段伸出.在这里下处理. 代码: /** * ...
- C#关于HttpClient的应用(二):融云IM集成
public class RcHttpClient:BaseHttpClient { private String appKey; private String appSecret; public R ...
- oracle_根据表名拼装语句
1.-----批量删除用户下所有表数据------保留表结构 eg: 批量删除用户下的所有表数据 SELECT 'TRUNCATE TALBE '||TABLE_NAME||';' FROM USER ...
- 使用php-fpm状态页观察当前的php-fpm状态
对于php-fpm的參数设置,非常多情况下有这种疑问,就是内置的几个參数比如pm.max_children,pm.start_servers等这几个參数究竟该设置最多为多少才合适.事实上这几个參数往往 ...
- Mac在结构quick cocos2d-x编译环境
关于 Quick 很多其它的使用说明可參考安装文件夹下的 README 文件. Quick-Coco2d-x开发工具 普通情况下,我们通常都会採用Cocos Code IDE作为开发工具来高速开发游戏 ...
- C++中避免内存泄露常见的解决方式
常见内存泄露及解决方式-选自ood启发录 new/delete, array new/arrray delete匹配 case 1: 在类的构造函数与析构函数中没有匹配地调用 new/delete! ...