DbUtility v3 背后的故事

时间

  • DbUtility v3构思了差不多大半年,真正开发到第一个版本发布到NuGet却只花了50天。中途大量时间在完善 Jumony 3,只有三周来开发DbUtility v3,其中总工时大概不超过20个小时。

  • DbUtility项目开始于2003年,2005年增加了实体转换的支持,2007年因为LINQ的发布,认为这个项目将来不会再有更新,遂开源,也是我开源的第一个项目,当时托管于Codeplex。

  • 每当我要快速搞定一个事情的时候,DbUtility总是最称手的工具,事实上在2007年之后DbUtility有四年没有任何修改,因为我觉得没有什么新的功能需要。

  • 如果不是眼馋.NET Framework 4.5新增的异步支持以及越来越多需要定制化查询结果(例如包装成Dictionary)的需求,DbUtility可能到现在都不会重写。

设计

  • DbUtility v3花了很长的时间来构思他的API设计,希望既能兼容之前的形式,保持简洁,流畅的特点,又利于扩展。下了很大的决心才最终敲定db.T( xxx ).ExecuteXXX()这样的形式,这与之前是不兼容的,所以新发布了一个NuGet包,避免原来的项目升级大面积的编译错误。

  • 利用扩展方法实现的API具有可以自行扩展以及整体切换的特点。这一风格是Jumony首创的,DbUtility把这个手法运用的更为娴熟了。

  • 同样花了很长的时间才敲定同时提供T和Template两个一模一样的方法,事实上T是Template的缩写。虽然具备智能提示可以非常便捷的输入Template,但我仍然认为,T这样的缩写,可以最大限度减少代码的行宽,不带来额外的噪声污染。

  • db.T( xxx )将不会执行查询,必须使用db.T( xxx ).ExecuteNonQuery()一直是整个设计中的一大痛处,因为可能会忘记写.ExecuteNonQuery。但是的确没有办法解决。

  • DbUtility的结果构建器,即ExecuteXXX方法,原本为了简洁是打算去掉Execute前缀的,例如:db.T( “SELECT * FROM Users” ).ExecuteEntities()原本是打算写成db.T( “SELECT * FROM Users” ).Entities()。但是由于考虑到某些查询构建器(即T(xxx))可能难以在一个方法内写完,需要多次调用构建最终的查询,此时执行查询的方法和构建查询的方法将没有明显的区分,故而依然保留Execute这个前缀。

    • 譬如说db.Table( "Users" ).Fields( "*" ).ExecuteEntities<User>()
  • 得益于新的架构设计,Jumony的结果构建器扩展方法写起来非常简单,所以我一口气提供了十几个用于构建不同类型结果的扩展方法。

技术

  • DbUtility拥有理论上性能最好的实体转换器,其原理是根据实体类型直接Emit一个转换器方法出来进行实体转换,而Emit出来的这个方法则巧妙地利用类型字典被缓存。这两项技术都是.NET的不传之秘,较之不使用这两项技术的实现方式性能不在一个数量级。

  • DbUtility的API将C#的泛型和类型推断运用到了极致,事实上诸如T这样的扩展方法,接受的第一个参数的类型是IDbExecutor,而SqlDbUtiltiy类型恰好实现了这个接口,所以可以调用。也就是说如果哪个数据库的查询器不支持参数化查询(没有实现这个借口),那么就点不出T出来。更神奇的是如果数据库查询器不支持异步查询,那么所有的异步API也会自动消失。

  • DbUtility的异步API实现贯彻了许多可以异步的地方,如打开数据库连接,执行查询。目前只剩下DataReader.Read方法没有调用异步版本,这将在后面的更新中解决。DbUtility恐怕也是第一个实现异步API的数据库访问帮助器。

  • Java移植项目在充分利用C#语法特性上简直令人发指,各种莫名其妙不符合.NET命名规则的API搞得各种乌烟瘴气。而DbUtility不仅仅充分利用了泛型、扩展方法一系列特性,更提供了运算符重载,可以非常直观的把参数化查询像拼接字符串一样拼接起来。

  • 在开发DbUtility v3的时候的确考虑过推出一个面向.NET Framework 3.5的版本,但是因为要同时维护两个版本过于费力。且DbUtility并非我的重心,故而作罢。但事实上删除DbUtility内所有的异步API,便可以得到在3.5下编译通过的代码。

 

优势

很多人会问我,DbUtility的优势在哪里?

事实上我一点儿都不想讨论这个问题,从根本上来说,DbUtility仅仅只是因为用了太多年非常顺手所以改进了一下让其与时俱进而已。

由于是超轻量级的数据库访问框架,代码量甚至都不过千行,可以说大家都是一样的,半斤八两没有区别。除非哪个不用Emit来做实体转换(这种垃圾应该赶紧扔掉)会造成性能下降。

但是总的来说,DbUtility仍然有一些特有的东西是其他轻量级框架难以企及的:

异步数据库查询
DbUtility v3率先推出了异步数据库查询实现,并将在后面不断完善。
可扩展的API
DbUtility v3采用了和Jumony项目一样的可扩展API设计,任何人任何第三方都可以在不修改现有代码之下对现有API进行扩展。
可替换和自定义的API
不仅仅是可以扩展现有API,甚至可以把整个API给替换掉。简单来说,如果你喜欢,甚至可以把DbUtility的API给换成Dapper一模一样的,但最终还是以DbUtility的核心在驱动。
参数化查询抽象
在v3的设计中,增加了抽象的参数化查询对象,参数化查询对象是与数据库无关的,在支持参数化查询的数据库,将会尝试采用参数化查询。而在不支持参数化查询的数据库,则尝试将参数值进行相应处理,以避免注入式问题。
结构化查询抽象
在将来,DbUtility 还将增加结构化查询抽象,将SQL查询抽象为语法树,通过方法来构建。在执行时再根据实际的数据库转换为相应的语法查询。
查询执行器、查询、结果构建器分离架构
吸取之前的经验,新的架构可以使得三部分独立的扩展,和谐的统一。

事实上DbUtility是一个面向真正程序员的超轻量数据访问框架,其拥有极大的可扩展性,并且扩展起来极为简便。这是DbUtility相较于其他超轻量数据访问框架的最大优势。

未来

DbUtility 即将到来的功能包括:

  • 更丰富的配置项

    • 例如不要总是异步打开连接(因为连接池内很可能已经存在连接)
    • 查询超时时间
  • 更好的异步支持(异步的Read调用)
  • 更好的存储过程支持
  • 查询日志记录和查询事件追踪(例如执行了哪些查询,执行了多久)。

在未来的版本中将会添加:

  • 更多的数据库支持(譬如Excel?!)
  • 结构化的 SQL 查询构建工具
  • 自定义类型映射(例如XML字段映射到XDocument)

以及更多,,,,

 

参与

DbUtility是一个开源项目,其足够轻便和简单,所以参与到DbUtility的开发过程中也是非常简单的,您可以通过以下的方式来参与:

DbUtility v3 背后的故事的更多相关文章

  1. 更好的 java 重试框架 sisyphus 背后的故事

    sisyphus 综合了 spring-retry 和 gauva-retrying 的优势,使用起来也非常灵活. 今天,让我们一起看一下西西弗斯背后的故事. 情景导入 简单的需求 产品经理:实现一个 ...

  2. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  3. 背后的故事之 - 快乐的Lambda表达式(二)

    快乐的Lambda表达式 上一篇 背后的故事之 - 快乐的Lambda表达式(一)我们由浅入深的分析了一下Lambda表达式.知道了它和委托以及普通方法的区别,并且通过测试对比他们之间的性能,然后我们 ...

  4. ASP.NET Web API自身对CORS的支持: EnableCorsAttribute特性背后的故事

    从编程的角度来讲,ASP.NET Web API针对CORS的实现仅仅涉及到HttpConfiguration的扩展方法EnableCors和EnableCorsAttribute特性.但是整个COR ...

  5. DbUtility v3

    DbUtility v3 历史 七年前,也就是2007年,我在博客园写了一篇博文,开源并发布了恐怕是我第一个开源项目,DbUtility.其设计的初衷就是为了简化ADO.NET繁琐的数据库访问过程,提 ...

  6. printf背后的故事

    printf背后的故事 说起编程语言,C语言大家再熟悉不过.说起最简单的代码,Helloworld更是众所周知.一条简单的printf语句便可以完成这个简单的功能,可是printf背后到底做了什么事情 ...

  7. using关键字背后的故事!

    using关键字的作用: 1:可以引入命名空间2:可以释放资源 *****不能使用using语句完全替换掉(try-catch-finally)语句(无法进行异常处理) 在出了using语句的{}后, ...

  8. Mac OS X 背后的故事

    Mac OS X 背后的故事 作者: 王越  来源: <程序员>  发布时间: 2013-01-22 10:55  阅读: 25840 次  推荐: 49   原文链接   [收藏]   ...

  9. 联想手机#P1来了#P1背后的故事系列

    http://bbs.lenovo.com/forum.php?mod=viewthread&fid=928&tid=560992&extra=page%3D1 联想手机#P1 ...

随机推荐

  1. Spring(5)—— 注解

    注解Annotation,是一种类似注释的机制,在代码中添加注解可以在之后某时间使用这些信息.跟注释不同的是,注释是给我们看到,java虚拟机不会编译,注解也是不编译的,但是我们可以通过反射机制来读取 ...

  2. jquery attr()方法

    在JS中设置节点的属性与属性值用到setAttribute(),获得节点的属性与属性值用到getAttribute(),而在jquery中,用一个attr()就可以全部搞定了,赞一个先 ^^ jque ...

  3. 关于如何在Android、Java等非微软平台上建立高信任的SharePoint应用程序

    关于如何在非微软平台上建立高信任的SharePoint应用程序 原文 :http://blogs.msdn.com/b/kaevans/archive/2014/07/14/high-trust-sh ...

  4. iOS 二维码扫描

    // 导入 AVFoundation.framwork 框架#import "HDCodeViewController.h" #import "HDNormalViewC ...

  5. PS技巧:如何优雅的抠公章?

    搞设计的很苦逼,整天面对各种各样任务,除了修图.排版外,还时不时会有些另类需求.这时如果掌握一些小技巧就不用临时抱佛脚啦. 下面献上一计:教大家怎么用PS抠公章.有需要的拿去,PS:不要干坏事吆! 效 ...

  6. MVP ComCamp & GCR MVP Openday 2014

    今年的MVP Openday与往年不一样,加入了Community Camp环节,即社区大课堂.其主要形式是由MVP作为讲师提供包括Developer和IT Pro方向的课程,地点是在北京国际会议中心 ...

  7. Write on ……… failed: 112(failed to retrieve text for this error. Reason: 15105)

    早上检查数据库的备份邮件时,发现一台Microsoft SQL Server 2008 R2 (SP2)数据库的Maintenance Report有错误 在SSMS里面执行Exec YourSQLD ...

  8. FFmpeg编译找不到库文件

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

  9. OpenSessionInViewFilter配置和作用

    Spring为我们解决Hibernate的Session的关闭与开启问题. Hibernate 允许对关联对象.属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Sessio ...

  10. x01.Weiqi.12: 定式布局

    定式 下一步当将定式保存到数据库中,如布局中的代码所示,但其初始的代码更有利于理解.以小飞挂为例: // 0 // + 0 0 // + // // + List<Pos> P_LuSta ...