如何通路資料庫?一個老掉牙的問題,方法多了去了,什麼直接使用ado.net、使用SQLHelp、使用微軟的企業庫、使用ORM、使用LinQ to SQL等等,還可以使用自己封裝的函數庫,這裡我就想說一下我的資料通路函數庫的使用方法。
您可能會說了,這麼簡單的東東還用說嗎,重複制作輪子有意義嗎?這個嘛,個人有個人的看法了,我也不多說了,先看使用方法吧。
忘記說了,我的資料通路函數庫不是靜态的,是以需要先執行個體化。
DataAccessLibrary dal = DALFactory.CreateDAL();
1、删除一條資料,不使用事務
protected void Btn_Del_Click(object sender, EventArgs e)
{
//不用事務,直接删除資料
string sql = "delete from News_NewsInfo where newsID = 18 ";
//執行SQL語句
dal.ExecuteNonQuery(sql);
判斷是否出現異常 和 是否真的删除了一條資料#region 判斷是否出現異常 和 是否真的删除了一條資料
//判斷是否出現異常
if (dal.ErrorMessage.Length > 0)
//出現了異常,用戶端彈出提示資訊
Functions.PageRegisterAlert(Page,"删除資料的時候發生異常,請與管理者聯系!");
return;
}
//判斷是否真的删除了一條資料
//ExecuteRowCount 會傳回操作影響的行數(不包括select語句)
if (dal.ExecuteRowCount != 1)
//沒有正确删除一條資料,用戶端彈出提示資訊
Functions.PageRegisterAlert(Page, "沒有正确删除這條資料,請與管理者聯系!");
#endregion
}
2、删除多條資料,使用事務
protected void Btn_DelMore_Click(object sender, EventArgs e)
//使用事務,删除多個表裡面的資料
//開啟一個事務
dal.TranManager.TranBegin();
string sql = "delete from News_NewsInfo where newsID = 13 ";
//資料通路函數庫内部會自動復原事務,外部不用復原!
Functions.PageRegisterAlert(Page, "删除資料的時候發生異常,請與管理者聯系!");
//沒有産生異常,内部并沒有自動復原事務,是以請調用復原的函數,復原事務!
dal.TranManager.TranRollBack();
sql = "delete from News_NewsInfo where newsID = 14 ";
//可以繼續執行其他的操作,不僅僅是删除語句,insert、Update語句都可以執行。
//執行之後都要進行判斷
//所有的操作都正确執行完畢之後,需要送出事務
dal.TranManager.TranCommit();
//注意,事務不支援嵌套!
3、使用參數化SQL語句添加資料
參數化SQL語句的方式添加資料#region 參數化SQL語句的方式添加資料
//清除參數
dal.ParameterManager.ClearParameter();
//添加參數
dal.ParameterManager.AddNewInParameter("@Title", "參數化SQL語句的标題", 50); //nvarchar類型的參數,需要指定長度
dal.ParameterManager.AddNewInParameter("@Content", "嘻嘻哈哈"); //ntext 類型的不需要指定長度
dal.ParameterManager.AddNewInParameter("@AddedDate", DateTime.Now); //日期型的
dal.ParameterManager.AddNewInParameter("@Hits", 3); //int型的
//執行參數化的SQL語句,傳回新添加的資料的ID值,隻限于自增字段的表。
string newID = dal.InsertData("News_NewsInfo");
Response.Write(newID);
Response.Write("<BR>" + dal.ExecuteRowCount);
Functions.PageRegisterAlert(Page, "添加資料的時候發生異常,請與管理者聯系!");
//判斷是否真的添加了一條資料
//由于最後使用了select scope_identity() as a1 來得到新增記錄的主鍵值,是以ExecuteRowCount值為零。
//我還不知道沒能正确添加資料的話 scope_identity()會傳回什麼?是以這裡就不知道要怎麼判斷了,呵呵
//if (newID != 0)
//{
// //沒有正确删除一條資料,用戶端彈出提示資訊
// Functions.PageRegisterAlert(Page, "沒有正确添加這條資料,請與管理者聯系!");
// return;
//}
4、使用儲存過程添加資料
存儲過程的方式添加資料#region 存儲過程的方式添加資料
//和參數化的SQL語句基本相同,不同點有兩個地方,一個是要事先建立存儲過程,一是使用ExecuteNonQuery。
dal.ParameterManager.AddNewInParameter("@Title", "儲存過程的标題", 50); //nvarchar類型的參數,需要指定長度
//添加傳回型的參數
dal.ParameterManager.AddNewOutParameter("@NewsID",DbType.Int32 );
//存儲過程的名稱要以Proc開頭
//如果您不習慣Proc開頭的話,那麼需要修改資料通路函數庫的内部函數。
//不建議使用xp_、sp_等開頭,因為系統的存儲過程的名稱是以這些開頭的。
//執行儲存過程
dal.ExecuteNonQuery("Proc_News_Mod");
//擷取儲存過程的參數
newID = dal.ParameterManager["@NewsID"].Value.ToString();
Response.Write("<BR>" + newID);
判斷是否出現異常 和 是否真的添加了一條資料#region 判斷是否出現異常 和 是否真的添加了一條資料
//沒有正确添加一條資料,用戶端彈出提示資訊
Functions.PageRegisterAlert(Page, "沒有正确添加這條資料,請與管理者聯系!");
5、使用參數化SQL語句修改資料
參數化SQL語句的方式修改資料#region 參數化SQL語句的方式修改資料
dal.ParameterManager.AddNewInParameter("@AddedDate", DateTime.Now); //日期型的
//修改存儲過程的參數的值
dal.ParameterManager["@Title"].Value = "後來修改了";
//執行參數化的SQL語句,設定條件已修改資料。
dal.UpdateData ("News_NewsInfo","NewsID = 21");
判斷是否出現異常 和 是否真的修改了一條資料#region 判斷是否出現異常 和 是否真的修改了一條資料
Functions.PageRegisterAlert(Page, "修改資料的時候發生異常,請與管理者聯系!");
//判斷是否真的修改了一條資料
Functions.PageRegisterAlert(Page, "沒有正确修改這條資料,請與管理者聯系!");
6、使用儲存過程修改資料
存儲過程的方式修改資料#region 存儲過程的方式修改資料
dal.ParameterManager.AddNewInParameter("@Title", "儲存過程的标題有修改了————", 50); //nvarchar類型的參數,需要指定長度
dal.ParameterManager.AddNewInParameter("@NewsID", 25); //修改條件
擷取資料#region 擷取資料
protected void Btn_DataTable_Click(object sender, EventArgs e)
string sql = "select * from News_NewsInfo";
//擷取DataTable
DataTable dt = dal.ExecuteFillDataTable(sql);
//擷取DataSet
DataSet ds = dal.ExecuteFillDataSet(sql);
//擷取第一條記錄的第一個字段
sql = "select top 1 title from News_NewsInfo where NewsID = 21";
string NewsTitle = dal.ExecuteString(sql);
//擷取第一條記錄的多個字段,用于字段比較少的情況
sql = "select top 1 title,Content,AddedDate,Hits from News_NewsInfo where NewsID = 21";
string[] NewsInfo = dal.ExecuteStringsBySingleRow(sql);
//擷取每一條記錄的第一個字段,有的時候會需要
sql = "select hits from News_NewsInfo";
string[] HitList = dal.ExecuteStringsByColumns(sql);
//判斷是否存在一條記錄
sql = "select top 1 1 from News_NewsInfo where title = '一個标題'";
if (dal.ExecuteExists(sql))
//存在這條記錄
else
//沒有找到這條記錄
#endregion
資料通路函數庫的特點
1、支援多種資料庫。基于ado.net2.0 ,使用System.Data.Common.DbProviderFactory 來實作。
2、調用友善、簡捷。一般一行語句即可搞定。
3、對事務、儲存過程的參數進行了封裝,以達到簡單好用的目的。
4、可以在内部拼接參數化的SQL語句,省去了在外部寫參數化的SQL語句的煩惱。
5、使用一個屬性來代替異常處理,隻需要檢查這個屬性值,即可知道是否發生異常。
6、産生異常的時候會記錄下SQL語句(或者儲存過程的名稱)、錯誤描述、時間、網頁即URL參數,以便于調試、修改錯誤。
這些代碼應該寫在哪一層?
從文法的角度來講,寫在哪一層都可以通過編譯。從流行的角度來講呢,應該寫在資料層。從我個人的角度來說呢,我是直接寫在了aspx.cs檔案裡了,為什麼要這麼做呢?友善!
另一個原因就是——我不知道要怎麼分?不都寫在aspx.cs檔案裡面寫在哪呢?建立一個.cs檔案,美其名曰“資料層”,寫一個函數,把代碼拷貝進去。然後在建立一個.cs檔案,美其名曰“業務邏輯層”,再在這裡調用剛寫的那個函數,最後在.aspx.cs檔案裡面調用?這可就是純粹為了分層而分層了。我覺得沒有必要,呵呵。
另外,就是這個操作習慣上的差别,讓我走到了和主流不一樣的道路!至少到目前為止,我還是覺得我的這個方向是沒有錯誤的。
Ps:
我的思路有一點另類,我的目的就是外部調用的時候一定要簡單,不必要的“啰嗦”一定要去掉,而資料通路函數庫的内部代碼可以多一點,函數的功能可以細緻一些(比如擷取資料的地方,設定了好幾個函數)。
使用SQLHelp的時候,為什麼要在外部執行個體化一個connection?為什麼要在外部建立儲存過程的參數?這麼麻煩,為什麼不能把這些都封裝進去呢?是以我把這些都封裝進去了。
變與不變
我說一下我的想法。就以上面的例子舉例。假設News_NewsInfo表裡面的“Title”字段想要改名,改成“NewsTitle”,那麼我的代碼要怎麼改呢?
我隻需要把
dal.ParameterManager.AddNewInParameter("@Title", "參數化SQL語句的标題", 50);
改成
dal.ParameterManager.AddNewInParameter("@NewsTitle", "參數化SQL語句的标題", 50);
就可以了,那麼本質上我修改了什麼呢?我修改了一個字元串的值!
函數本身是不變的,變化的是參數值,就是那個字元串,就是那個字段名。不知道說道這裡您有答案了沒?就是說我可以把表名、字段名放在“配置”裡面,用的時候讀取出來,給函數的參數指派,這樣當字段名變化的時候,我隻需要修改“配置”裡的資訊就可以了,不需要修改代碼。
您可能會問了,修改代碼裡的字元串是修改,修改“配置”也是修改,後者有什麼優勢嗎?優勢那可就大了。留一個想象的空間吧,暫時先不說了。