DbUtility v3

历史

七年前,也就是2007年,我在博客园写了一篇博文,开源并发布了恐怕是我第一个开源项目,DbUtility。其设计的初衷就是为了简化ADO.NET繁琐的数据库访问过程,提供极为简洁流畅的语法访问数据库,像这样:

dbUtility.ExecuteSingleRow("SELECT username, userdata FROM Users WHERE ID = {0}", userId );

这一行代码将自动创建和打开数据库链接、创建命令对象、包装参数、执行查询并将结果包装成DataRow返回。

时过境迁,七年后的现在,我们有了非常多的重量级的ORM如NHibernate、EntityFramework,和各种快速访问数据库的框架。但有些时候,我们仍然会希望,执行一个简单的SQL查询,并获得其结果。

这时候我经常会想起DbUtility这个家伙,所以在七年后的今天,我把DbUtility的所有代码重新写了一次,推出了这个超轻量级数据库访问帮助器的最新版本,DbUtility v3,目前在GitHub上开源

简单查询

如果你从来没有听说过这个东西,也没有关系,DbUtility是被设计为超轻量级(无需任何额外的配置,不会产生任何未知的行为),随手可用(语法简单、直接、明了)的数据库访问帮助器。

一个典型的DbUtility v3的代码像是下面这样:

db.T( "SELECT Username FROM Users WHERE ID = {0};", userId ).ExecuteScalar<string>();

几乎每个数据库的查询差不多都是这种形式,其中可以分为三个部分:

查询执行器,即上面代码中的 db ,这个东西负责执行查询,其与数据库直接相关,一般我们可以使用一个连接字符串配置或者连接字符串来创建查询执行器的实例:

var db = new SqlDbUtility( "数据库连接字符串" );

var db = SqlDbUtility.Create( "连接字符串名称" );

紧跟着查询执行器的部分是查询构建器,这一部分决定了数据库具体要执行的查询。也就是上面代码中的 .T( "SELECT Username FROM Users WHERE ID = {0};", userId ) 部分,T的意思是Template,即模板,这也是DbUtility最基本的查询构建方式,通过SQL指令模板来构建。我们可以使用类似于string.Format的语法指定字符串模板和模板参数。但与直接调用string.Format不同的是,这个模板中的参数会被转换为参数化查询中的参数,从而没有注入式漏洞的隐患。即上述的查询模板最终转换成的SQL大体上是这样的:

DECLARE @Param0 AS int = userId-value;
SELECT Username FROM Users WHERE ID =@Param0;

T或者Template方法(事实上T是缩写)会解析查询模板并创建一个抽象的参数化查询对象,参数化查询对象会根据具体的数据库产生相应的参数化查询进行执行。

最后的一部分是结果构建器,也就是上面代码中的 .ExecuteScalar<string>() ,ExecuteScalar即是取出查询结果中的第一行第一列。

DbUtility v3提供了极为丰富的结果构建器,除了ExecuteScalar、ExecuteNonQuery、ExecuteDataTable、ExecuteFirstRow这些常见常用的之外,还有自动将结果包装成实体的ExecuteEntity和ExecuteEntities,包装成动态对象的ExecuteDynamicObject和ExecuteDynamics等等等等。丰富的结果构建器可以极大地简化你访问数据库的代码。

不过最重要的是,DbUtility v3设计了一个便于扩展的架构,所有的查询构建器、结果构建器,全部可以简单地自定义扩展,或者说事实上整个DbUtility提供的所有的查询构建器和查询结果构建器本来就是用扩展方法扩展出来的。

进阶

如果你要开启数据库事务,使用DbUtility也非常的方便:

using( var transaction = db.BeginTransaction() )
{
transaction.T( "SELECT Username FROM Users WHERE ID = {0}", userId ).ExecuteScalar<string>();//事务对象可以直接当做查询执行器来使用。 //... transaction.Commit();//提交事务,若在离开using块之前没有提交事务,则事务会自动回滚。
}

异步查询数据库也非常的简单:

var username = await db.T("SELECT Username FROM Users WHERE ID = {0};", userId ).ExecuteScalarAsync<string>();//加上Async后缀即是访问异步版本。

Jumony的示例项目全部数据库访问改用DbUtility后,比起EntityFramework来说,不仅配置消失了,性能也更好了(因为DbUtility是超轻量级的),更重要的是,结合MVC 4的异步Action,我们可以非常简单的在ASP.NET中异步访问数据库以获得更大的吞吐量:

public async Task<ActionResult> Index()
{
return View( "index", await dbUtility.T( "SELECT ID, Title, Completed FROM Tasks" ).ExecuteEntitiesAsync<TodoTask>() );
}

尾声

在马上发布的更新中,我们可以简单地把多个参数化查询对象像拼接字符串一样拼接起来:

var query = db.T( "SELECT * FROM Users" );

query += "WHERE" + Db.Join( "AND", Db.T( "Age > {0}", age ), Db.T( "FirstName LIKE '%'+{0}+'%'", name ) );

var result = query.ExecuteEntities<User>();

在未来的版本中,将支持更多的数据库类型(如Excel),更好的查询构建(值得期待的超轻量SQL语法: db.Q( "users.username ?users.userId = @0", userId ) )。

DbUtility v3现在已经可以通过 NuGet 获取。

全线开源项目全部在GitHub以Apache协议开源,DbUtility:超轻量数据访问帮助,Jumony:真正的HTML分析、处理、绑定、视图引擎,WebTest:在ASP.NET环境直接进行单元测试,LogUtility:文本日志记录利器。

以上项目均可以在 NuGet 下载。

DbUtility v3的更多相关文章

  1. DbUtility v3 背后的故事

    DbUtility v3 背后的故事 时间 DbUtility v3构思了差不多大半年,真正开发到第一个版本发布到NuGet却只花了50天.中途大量时间在完善 Jumony 3,只有三周来开发DbUt ...

  2. 扩展 DbUtility (1)

    本文原始路径: https://www.zybuluo.com/Ivony/note/14074 前言 DbUtility v3 是一个开源的轻量级数据库访问框架,源代码通过 Apache 协议发布, ...

  3. DbUtility Ex

    扩展 DbUtility (1) 2014-05-22 21:48 by Ivony..., 234 阅读, 3 评论, 收藏, 编辑 本文原始路径: https://www.zybuluo.com/ ...

  4. DBImport V3.7版本发布及软件稳定性(自动退出问题)解决过程分享

    DBImport V3.7介绍: 1:先上图,再介绍亮点功能: 主要的升级功能为: 1:增加(Truncate Table)清表再插入功能: 清掉再插,可以保证两个库的数据一致,自己很喜欢这个功能. ...

  5. AEAI DP V3.6.0 升级说明,开源综合应用开发平台

    AEAI DP综合应用开发平台是一款扩展开发工具,专门用于开发MIS类的Java Web应用,本次发版的AEAI DP_v3.6.0版本为AEAI DP _v3.5.0版本的升级版本,该产品现已开源并 ...

  6. atitit 商业项目常用模块技术知识点 v3 qc29

    atitit 商业项目常用模块技术知识点 v3 qc29 条码二维码barcodebarcode 条码二维码qrcodeqrcode 条码二维码dm码生成与识别 条码二维码pdf147码 条码二维码z ...

  7. Atitit. 提升存储过程与编程语言的可读性解决方案v3 qc25.docx

    Atitit. 提升存储过程与编程语言的可读性解决方案v3 qc25.docx 1. 大原则:分解+命名1 1.1. 命名规范1 1.2. 分层.DI和AOP是继OO1 1.3. 运算符可读性一般要比 ...

  8. 高效 Java Web 开发框架 JessMA v3.5.1

    JessMA 是功能完备的高性能 Full-Stack Web 应用开发框架,内置可扩展的 MVC Web 基础架构和 DAO 数据库访问组件(内部已提供了 Hibernate.MyBatis 与 J ...

  9. 高性能 TCP & UDP 通信框架 HP-Socket v3.5.3

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

随机推荐

  1. iOS使用Zbar扫描二维码

    iOS使用Zbar扫描二维码 标签(空格分隔):二维码扫描 iOS Zbar64位 正文: 首先下载一个支持64位系统的ZbarSDK的包,保存在了我的云盘里,地址:ZbarSDK 把文件拖到工程里面 ...

  2. iOS程序逆向Mac下常用工具——Reveal、HopperDisassemble、IDA

    原文在此 一.Reveal 1 一般使用     Reveal是ITTY BITTY发布的UI分析工具,可以很直观的查看App的UI布局.如下图所示:     Reveal是需要付费的,需要89美元, ...

  3. Adobe AIR 中为不同尺寸和分辨率屏幕适配

    在 Adobe AIR 中为不同屏幕尺寸的多种设备提供支持 http://www.adobe.com/cn/devnet/air/articles/multiple-screen-sizes.html ...

  4. SqlServer--用代码创建和删除数据库或表

    创建数据库,创建表,设置主键数据库的分离和附加MS SQLServer的每个数据库包含:1个主数据文件(.mdf)必须.1个事务日志文件(.ldf)必须.可以包含:任意多个次要数据文件(.ndf)多个 ...

  5. ORACLE字符集基础知识

    概念描叙    ORACLE数据库有国家字符集(national character set)与数据库字符集(database character set)之分.两者都是在创建数据库时需要设置的.国家 ...

  6. MongoDB学习笔记~MongoDB实体中的值对象

    回到目录 注意,这里说的值对象是指在MongoDB实体类中的,并不是DDD中的值对象,不过,两者也是联系,就是它是对类的补充,自己本身没有存在的价值,而在值对象中,也是不需要有主键Id的,这与DDD也 ...

  7. FFmpeg编译找不到库文件

    在编译FFmpeg的时候,用./configure 进行配置,经常会出现找不到库文件的情况,原因大概就两个: 1.没有安装库文件或者安装的库文件版本不对 2.FFmpeg没有找到库文件 前者的问题好解 ...

  8. android 拔打电话功能

    private void phoneCall(String num) { String phoneNum = "tel:" + num; Uri smsToUri = Uri.pa ...

  9. java中Class对象详解和类名.class, class.forName(), getClass()区别

    一直在想.class和.getClass()的区别,思索良久,有点思绪,然后有网上搜了搜,找到了如下的一篇文章,与大家分享. 原来为就是涉及到Java的反射----- Java反射学习 所谓反射,可以 ...

  10. NYOJ---540奇怪的排序

    奇怪的排序 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 最近,Dr. Kong 新设计一个机器人Bill.这台机器人很聪明,会做许多事情.惟独对自然数的理解与人类不一 ...