資料通路層的使用方法。
資料通路層的使用方法
一、操作語句部分
簡單的說就是傳入一個操作語句,然後接收傳回值就可以了。為了簡化代碼和提高效率,是以呢設定了五種傳回類型。
1、 DataSet
函數名稱:DateSet ds = RunSqlDataSet(查詢語句)
傳入一個查詢語句(多條select 的查詢語句),然後接收傳回值就可以了。
沒有記錄傳回 null
2、 DataTable
函數名稱:DateTable dt = RunSqlDataTable(查詢語句)
傳入一個查詢語句(一條select 的查詢語句),然後接收傳回值就可以了。
3、 DataRow
函數名稱:DataRow dr = RunSqlDataRow(查詢語句)
4、 String[]
函數名稱:string[] str = RunSqlStrings (查詢語句)
5、 String
函數名稱:string str = RunSqlGetID (查詢語句)
6、 Null
函數名稱:RunSql (操作語句)
傳入一個操作語句(insert 、update、delete的操作語句)。
說明:參數都是字元串型的。
二、存儲過程部分
簡單的說就是和查詢語句的很類似了,隻不過多了個存儲過程的參數。
函數名稱:DateSet ds = RunStoreDataSet(存儲過程的名稱)
傳入存儲過程的名稱,然後接收傳回值。
函數名稱:DateTable dt = RunStoreDataTable(存儲過程的名稱)
3、 Null
函數名稱:RunStore (存儲過程的名稱)
傳入存儲過程的名稱。
三、存儲過程的參數(1)
如果沒有參數的話,那麼存儲過程的用法和查詢語句的也就一樣了。但是呢,大多數的存儲過程都是有參數的,不過有了參數我們也不怕!
我們可以用addNewParameter方法來添加存儲過程的參數。不用像SQLHelp那樣麻煩,還得傳入一個Parameter的對象。我們直接調用資料通路層的方法就可以了。
這裡通過函數重載的方式來區分不同的資料類型。以C#裡的資料類型為标準,對應SQL裡面的資料類型。
1、 int型的參數
這裡對應三個SQL Server的資料類型:int、tinyint、smallint
函數名稱:addNewParameter(string ParameterName,int ParameterValue)
ParameterName:參數名稱。
ParameterValue:參數值。
2、 bit型的參數
這裡對應一個SQL Server的資料類型:bit
函數名稱:addNewParameter(string ParameterName,bool ParameterValue)
3、 double型的參數
這裡對應兩個SQL Server的資料類型:float、real
函數名稱:addNewParameter(string ParameterName,double ParameterValue )
4、 string型的參數
這裡對應七個SQL Server的資料類型:char、nchar、varchar、nvarchar、uniqueidentifier、smalldatetime、datetime
函數名稱:addNewParameter(string ParameterName,string ParameterValue,int size)
Size: 參數的大小。
5、 ntext型的參數
這裡對應兩個SQL Server的資料類型:ntext、text
函數名稱:addNewParameter(string ParameterName,string ParameterValue)
6、 金額型的參數
這裡對應三個SQL Server的資料類型:decimal、smallmoney、money
函數名稱:addNewParameter(string ParameterName,decimal ParameterValue)
7、 說明
還有二進制類型的沒有處理。忘記要用C#的哪個類型來對應了。
這裡添加的參數都是輸入型(input)的,如果想設定輸出型的參數請看下面。
四、存儲過程的參數(2)
這裡講述如何設定輸出型(output)的參數,以及如何修改參數值、取值和清除參數
1、 設定輸出型參數
函數名稱:addNewParameter(string ParameterName,ZDIC.ParameterKind kind)
Kind:參數類型。
2、 擷取參數的傳回值
函數1名稱:getParameter(int ParameterIndex)
ParameterIndex:參數的序号。
通過參數的序号來傳回參數值。
函數2名稱:getParameter(string ParameterName)
ParameterName:參數的名稱。
通過參數名稱來傳回參數值。
3、 修改參數值
函數1名稱:setParameter(int ParameterIndex,string parameterValue)
通過參數的序号來修改參數值。
函數2名稱:setParameter(string ParameterName,string parameterValue)
通過參數名稱來修改參數值。
4、 清除參數
函數名稱:ClearParameter()
執行一下就行除了。
五、異常處理
這裡并不向上層抛出異常,取代的是給ErrorMsg屬性指派。如果程式正常執行,則ErrorMsg==”0”表示沒有發生異常;否則ErrorMsg的内容就是錯誤描述。
錯誤描述包括三個部分:函數名稱,執行的查詢語句(存儲過程)和系統給出的錯誤資訊。這樣呢就很容易發現出錯的地方,尤其是在使用查詢語句的時候。
六、錯誤日志
在發生異常的時候,會自動記錄錯誤資訊,以便日後的維護和修改錯誤。
錯誤日志以文本檔案的形式存放在 /log檔案夾下面,檔案名是yyyyMMdd的格式。
為什麼用文本檔案而不用資料庫?因為一般在正式使用後發生的異常大多都是由于資料庫造成的,是以很有可能在發生異常之後已經無法再向資料庫裡寫資訊了。而向文本檔案裡寫資訊一般是不會出錯的。
七、連接配接字元串及Connection對象
連接配接字元串是從 Connection.dll 裡面讀取的,其目的是适應連接配接字元串的各種變化。比如是否加密,用什麼算法加密;連接配接字元串存放在什麼地方?web.config、DLL、系統資料庫或者其他的什麼地方。引用Conection.dll後就可以很輕松的應對以上的這些要求。
八、事務處理
利用 Connection.BeginTransaction 等方法實作事務。沒有作嚴格的測試,因為目前還沒有用到。
九、更換資料庫
這裡是針對SQL Server 資料庫做的處理,也就是對SqlClinet進行的封裝。如果更換資料庫的話,那麼隻需要把Sql字樣換成對應的資料庫的表示就可以了。其他的作一些适當的調整就可以了。
十、使用示例
以新聞系統為例
1、 用查詢語句的方式擷取新聞清單,然後綁定Repeater控件。
DataAccessLayer dal = new DataAccessLayer();
Rpt.DataSource = dal.RunSqlDataTable("select NewsID,addedDate,title from news ");
if (dal.ErrorMsg.Length > 2 )
{
Response.Write(dal.ErrorMsg ); //輸出錯誤資訊
return;
}
Rpt.DataBind();
2、 用存儲過程的方式擷取新聞清單,然後綁定Repeater控件。
Rpt.DataSource = dal.RunStoreDataTable("Proc_News_list");
3、 用string[]的方式擷取一條新聞紀錄。然後給Label控件指派。
string sql = "select Title,AddedDate,Content from News where NewsID=" + NewsID
string[] Infos = dal.RunSqlStrings(sql);
if (Infos == null)
Response.Write("沒有這條新聞!");
Response.End();
Lbl_Title.Text = Infos[0];
Lbl_AddedDate.Text = Infos[1].Split(' ')[0];
Lbl_Content.Text = Infos[2];
4、 用DataRow的方式擷取一條新聞紀錄。然後給Label控件指派。
DataRow Infos = dal.RunSqlDataRow(sql);
Lbl_Title.Text = Infos["Title"].ToString();
Lbl_AddedDate.Text = Infos["AddedDate"] .ToString().Split(' ')[0];
Lbl_Content.Text = Infos["Content"] .ToString();
5、 用InsertDataStr和UpdateData實作添加、修改新聞。同時用RunSqlExists判斷新聞标題是否重複。
//判斷是修改還是添加
bool isAdd = false;
if (DG.SelectedIndex == -1) //利用DataGrid的狀态來判斷是添加還是修改。
isAdd = true;
//設定字段。這裡一定要用一個數組來表示,這是 InsertDataStr 函數的參數的要求!
string[] str1 = new string[2];
str1[0] = "title";
str1[1] = "Content";
//擷取使用者輸入的資訊,并且過濾危險字元
//這裡一定要用一個數組來表示,這是 InsertDataStr 函數的參數的要求!
string[] str = new string[2];
str[0] = this.Txt_Title.Text.Trim().Replace("'","");
str[1] = this.Txt_Content.Text.Trim().Replace("'","");
#region 資料驗證
if (str[0].Length == 0 )
Page.RegisterStartupScript("a",Functions.myAlert("請填寫新聞标題!"));
if (isAdd)
if (dal.RunSqlExists("select top 1 '1' from news where title='" + str[0] + "'" ))
{
Page.RegisterStartupScript("a",Functions.myAlert("已經有這個新聞标題了!"));
return;
}
else
if (dal.RunSqlExists("select top 1 '1' from news where title='" + str[0] + "' and NewsID <>" + DG.SelectedItem.Cells[0].Text))
#endregion
//添加新聞
dal.InsertDataStr("News",str1,str);
//修改新聞
dal.UpdateData("News",str1,str," NewsID=" + DG.SelectedItem.Cells[0].Text);
//檢查是否出現異常
Response.Write(dal.ErrorMsg ); //輸出錯誤資訊
//添加成功。進行相應處理
//修改成功。進行相應處理
6、 用RunStore 用的方式添加修改新聞
//擷取使用者輸入的資訊,存儲過程的方式就不用過濾了
string NewsTitle = this.Txt_Title.Text.Trim();
string NewsContent = this.Txt_Content.Text;
// 資料驗證
//标題是否重複的判斷由存儲過程來實作
//添加存儲過程的參數
dal.addNewParameter("@title",NewsTitle,100);
dal.addNewParameter("@Content",NewsContent);
//output型的參數
dal.addNewParameter("@ReturnMsg",ParameterKind.NVarChar );
if (!isAdd)
//修改新聞,需要給 @NewsID 負值。
dal.addNewParameter("@NewsID",Int32.Parse(DG.SelectedItem.Cells[0].Text))
//執行存儲過程
dal.RunStore("Proc_News_ModData");
string err = dal.getParameter("@ReturnMsg");//擷取參數的傳回值
{//添加狀态
if (err.Length > 1)
//顯示存儲過程裡面傳回的錯誤資訊,比如新聞标題重名等。
else
//添加成功
SetFormEmpty();
}
{//修改狀态
//修改成功
SetFormVisible(false);
7、 用RunSql 删除新聞
dal.RunSql("delete from News where NewsID=" + e.Item.Cells[0].Text);
8、 說明
除了添加修改的地方,代碼都是非常簡潔的。可以說隻用了一行就達到了目的。由于省去了實體層,資料通路層也變成了DLL類庫,是以說呢,從表面上看程式的結構就變成了一層結構了,也就是說隻需寫這些代碼就可以實作一個子產品的基本功能了。
再來看看添加修改的地方。雖然代碼好像多了一點,但是合并了添加、修改的共同的地方,減少了三分之一的代碼。可能會比三層結構的UI層的代碼量多一些,但是沒有實體層、業務邏輯層和資料通路層的代碼。重整體上來說減少了三倍的代碼量。
修改上也是很友善的。如果要修改字段名稱的話,隻需要修改str1數組裡對應的值就可以了;添加字段呢,隻需要增加str1和str數組的大小,并負值就可以了。省去了其他層的修改(因為根本就沒有在其他的地方寫代碼!)