七年前,也就是2007年,我在博客園寫了一篇博文,開源併發布了恐怕是我第一個開源項目,DbUtility。其設計的初衷就是爲了簡化ADO.NET繁瑣的數據庫訪問過程,提供極爲簡潔流暢的語法訪問數據庫,像這樣:html
dbUtility.ExecuteSingleRow("SELECT username, userdata FROM Users WHERE ID = {0}", userId );
這一行代碼將自動建立和打開數據庫連接、建立命令對象、包裝參數、執行查詢並將結果包裝成DataRow返回。git
時過境遷,七年後的如今,咱們有了很是多的重量級的ORM如NHibernate、EntityFramework,和各類快速訪問數據庫的框架。但有些時候,咱們仍然會但願,執行一個簡單的SQL查詢,並得到其結果。github
這時候我常常會想起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大致上是這樣的:async
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 下載。