DbEntry 主頁上已經有文檔,雖然是寫的英文,不過我的英文並不是很好,所以也都是很簡單的,所以這一次准備寫的兩三篇文章,不准備全面介紹,也不准備按照原文檔的順序,而是以 DbEntry 的發展來簡單介紹一下。
這第一篇先介紹一下執行 SQL。
DbEntry 開始於 2004 年,那個時候,還不是 ORM,開發它希望解決的問題是,簡化執行 SQL,以及保證關閉數據庫連接。
SqlConnection connection = new SqlConnection("connectionString");
connection.Open();
SqlCommand command = new SqlCommand("cmdText", connection);
command.ExecuteNonQuery();
command.Dispose();
connection.Close();
以上的代碼能保證關閉數據庫連接麼?當然不能,只要 command 和 reader 執行中有任何一個異常,後面的關閉指令將不會被執行。所以正規的做法應該是:
using (SqlConnection connection = new SqlConnection("connectionString"))
{
connection.Open();
using (SqlCommand command = new SqlCommand("cmdText", connection))
{
command.ExecuteNonQuery();
}
}
作為最佳實踐,上面這種使用 using 的方法是需要的,不過,因為其羅嗦,再寫了10個這種代碼後,遺漏掉一個還是可能的,所以,使用更簡單的方法,讓大家喜歡使用能保證連接關閉的方法,會更有效,這也是 DbEntry 的做法:
DbEntry.Context.ExecuteNonQuery("cmdText");
那麼使用 DataReader 的通常的代碼是什麼樣的呢?因為 DataReader 也需要及時的被關閉,我想大概是:
using (SqlConnection connection = new SqlConnection("connectionString"))
{
connection.Open();
using (SqlCommand command = new SqlCommand("cmdText", connection))
{
command.ExecuteNonQuery();
using(SqlDataReader reader = command.ExecuteReader())
{
// read data
}
}
}
DbEntry 中使用匿名方法(.Net 3.5 中叫 lambada 表達式,語法形式稍有差異)來實現,和上面代碼等效的代碼是:
DbEntry.Context.ExecuteDataReader(new SqlStatement("cmdText"),
reader =>
{
// read data
});
DbEntry 也支持讀取和更新 DataSet,讀取的語法如下:
DataSet ds = DbEntry.Context.ExecuteDataset("cmdText");
DbEntry 對待 cmdText,和其它的框架有些不同,它會自動掃描 cmdText,如果發現它是一個 identity 的話,就自動把它當作存儲過程來執行,反之則作為 SQL 語句來執行。當然,如果你想自己定義 cmdText 究竟是存儲過程還是 SQL 語句,也是可以的。如果是存儲過程,其參數類型,DbEntry 會自動查詢數據庫而得到,所以就不再需要填寫類型了:
DataSet ds = DbEntry.Context.ExecuteDataset("cmdText", 13 "tom");
記得以前的 Application Block 裡,有一個 SqlHelper,也是為了處理類似問題而做的,只不過其中使用了 Sql Server 特有的參數,使得它事實上只能用於 SQL Server。
事務的執行,在 DbEntry 裡,使用的也是匿名方法:
DbEntry.UsingTransaction(delegate
{
DbEntry.Context.ExecuteNonQuery("cmdText1");
DbEntry.Context.ExecuteNonQuery("cmdText2");
});
大家也許注意到了,這裡並沒有像 TransactionScope 那樣的 Commit 調用,這也正是匿名方法優於 using 語句之處,在這裡,執行完 SQL 調用後,如果沒有出現異常,DbEntry 就會自動調用 Commit 函數進行提交。
對於事務,DbEntry 有 UsingTransaction 和 NewTransaction 兩個函數,區別在於 UsingTransaction 會嘗試使用已經存在的事務,如果沒有則新建一個事務,而 NewTransaction 總是會啟動一個新的事務,一般來說,UsingTransaction 已經足夠了。這個設計的好處在於,如果我們已經定義了一個函數A,其中使用了事務,而另一個函數B要調用函數A,而且希望自己調用的 SQL 和函數A的 SQL 在一個事務內,用這種方式很簡單就能做到:
void FuncA()
{
DbEntry.UsingTransaction(delegate
{
DbEntry.Context.ExecuteNonQuery("cmdText1");
DbEntry.Context.ExecuteNonQuery("cmdText2");
});
}
void FuncB()
{
DbEntry.UsingTransaction(delegate
{
FuncA();
DbEntry.Context.ExecuteNonQuery("cmdText3");
DbEntry.Context.ExecuteNonQuery("cmdText4");
});
}
執行 SQL 是 DbEntry 的基石,ORM 部分也是調用這些方法完成 SQL 操作的,所以,這裡的事務操作,對於混合了 ORM,SQL 和存儲過程的情況,也同樣有效。關於執行 SQL 就說這些吧,其中還有不少細節問題,可以參考主站的文檔、單元測試以及源代碼
本文作者:未知