錯誤和失敗總會不可避免地在應用程式中出現。如果有人在MDB目錄之上又添加了一級新的檔案夾而“更新”了伺服器的分類樹,那麼將會發生什嗎?如果MDB名稱被更改了會怎樣?如果MDB檔案被損壞又該如何呢?以上每一個問題都將阻止對資料的成功串連並導致一個失敗頁面。好的編程實踐表明需要儘可能小心地對待任何失敗。
在討論實際命令之前,我們需要瞭解的是AccessDataSource控制項派生於SqlDataSource控制項。在大多數情況下,這隻是一個背景問題。但是當處理異常的時候,就必須使用實際上存在於(從而以之命名的)SQL資料來源對象之中的對象。
軟著陸的技術使用的代碼將在AccessDataSource控制項經曆OnSelected event時被觸發。當GridView從資料來源控制項請求資料時,這個事件將會在內部觸發。 處理串連錯誤的代碼就會檢查到從資料來源控制項傳遞過來的異常參數。AccessDataSource控制項沒有關於這個參數的自己的名稱,所以只能使用名稱SqlDataSourceStatus- EventArguments。如果異常參數為空白,那麼表示什麼事情都沒有發生。如果異常參數有一個值,那麼將檢查這個值。如果參數是OLEDB Exception類型的,那麼頁面上的警告標籤的文本將會有提示資訊。再次提醒您注意術語的使用。如果有一個AccessException類型,那將更明了,可惜實際上沒有這種類型。可以使用更加普通的OleDbException對象並以處理異常的命令結束指令碼。這樣將允許GridView繼續呈現,雖然沒有資料,並防止出現淺褐色背景的常規ASP.NET 2.0失敗頁面。因為GridView沒有得到任何資料,所以它將會顯示一個替換表格,表格中只有一個在其EmptyDataText屬性中顯示訊息的儲存格。
如果您在進行這些步驟中遇到困難,千萬不要感到悲觀;下一個練習將會進行示範。而現在,只需將代碼剪下並粘貼到頁面之中。在本書的後面,我將會討論如何建立一個用於串連失敗情況下的GridView的替換頁面以及處理錯誤事件的詳細內容。
試一試#4—— 處理AccessDataSource串連失敗
(1) 在ch02檔案夾中,建立一個名為TIO-4-ConnectionFailure-CS.aspx的檔案。在Design視圖中,添加一個指向Northwind 的AccessDataSource控制項至頁面,該控制項從表中選擇了所有列。
(2) 添加GridView用來顯示資料來源控制項中的資訊。同樣,添加一個標籤控制項,並將其命名為“Message”。
(3) 現在切換至Source視圖並對標記作一些修改,如下反白代碼所示。如果其中有<columns>標記部分,則將其刪除。留下的代碼應當如下所示:
<html>
<head id="Headl" runat="server">
<title>Chapter 2 TIO #4 Connection Failure to Access in C#</title>
</head>
<body>
<h3>Chapter 2 TIO #4 Connection Failure to Access in C#</h3>
<form id="forml" runat="server">
<asp:label ID="Message" runat="server"/><br/><br/>
<asp:gridview id="GridViewl" runat="server"
datasourceid="AccessDataSourcel"
AutoGenerateColumns="true"
EmptyDataText="No data records were returned" />
<asp:AccessDataSource ID="AccessDataSourcel" Runat="server"
selectcommand="Select * From Products"
datafile="~/App_Data/Northwind.mdb"
OnSelected="AccessDataSourcel_Selected"
/>
</form>
</body></html>
(4) 檢查頁面;在查看由Northwind售出的產品的時候,不應該出現問題。
(5) 現在將添加代碼來處理串連問題了。轉到頁面的頂部並進入如下指令碼。第一個樣本用C#編寫,第二個樣本用VB編寫。進入其中之一即可。
<%@ page language="C#" %>
<script runat="server">
void AccessDataSourcel_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
if (e.Exception != null)
{
if(e.Exception.GetType()==typeof(System.Data.OleDb.OleDbException))
{
Message.Text = "There was a problem opening a connection to the
database. Please contact the system administrator for this site.";
//Optionally set GridViewl.Visible = false;
e.ExceptionHandled = true;
}
}
}
</script>
<html> ...
以下是用VB編寫的指令碼。
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtmlll/DTD/xhtmlll.dtd">
<script runat="server">
Sub AccessDataSourcel_Selected(ByVal sender As Object, ByVal e As
SqlDataSourceStatusEventArgs)
If (Not e.Exception Is Nothing) Then
If TypeOf e.Exception Is System.Data.OleDb.OleDbException Then
Message. Text = "There was a problem opening a connection to the database. Please contact the system administrator for this site."
' Optionally set GridViewl.Visible = false
e.ExceptionHandled = True
End If
End If
End Sub
</script>
<html> ...
(6) 儲存並運行頁面。因為我們實際的串連還保持完好,所以現在還沒有任何問題。關閉瀏覽器。
(7) 現在將Northwind的MDB檔案從\App_Data移動至C:\Temp檔案夾中,這樣串連將會失敗。或者,可以修改代碼來嘗試串連Southwind.mdb。運行頁面並注意瀏覽器將顯示一個得體的失敗資訊。
(8) 如果移動了Northwind.mdb,那麼將其再移動回C:\BegAspNetDb\ App_ Data檔案夾中。
樣本說明#4—— 處理AccessDataSource串連失敗
首先,請回想一下AccessDataSource控制項是SqlDataSource的派生物,並且使用了應用於OLEDB資料來源的一系列異常,所以當引用了帶有SQL或者OLEDB名稱而不是Access名稱的對象時,請不要驚訝。
請觀察在頁面上進行的處理串連失敗的三個修改。第一,添加了GridView資料來源控制項的一個屬性,該屬性在GridView沒有從資料來源控制項中獲得任何資料時將會顯示一條訊息。第二,添加了資料來源控制項的一個屬性,該屬性在OnSelected事件發生時調用Data_Selected事件處理常式。請注意這處於DataSource事件中。雖然使用者沒有直接選擇 AccessDataSource控制項(也沒有向使用者呈現),但是當GridView向資料來源控制項請求資料時,選擇還是在內部發生了。第三,您編寫了這段指令碼。
該指令碼將會接收到幾個參數,其中之一就是異常。這裡沒有名為AccessDataSourceStatusEventArgs的對象。但是,可以獲得一個內部派生出 Access- DataSource 的基本對象:SQL DataSource。SqlDataSource對象具有可以提交至AccessDataSource控制項的狀態參數。如果沒有問題,則異常列表為空白。如果有一個異常,那麼代碼將會進行測試來查看拋出的異常是什麼類型。同樣地,也沒有像Access Exception一樣的對象。但是,AccessDataSource將異常放入更加普通的稱為OleDb Exception的對象中。假定在這個集合中的所有異常都是由串連失敗造成的。我們的代碼將作出反應,反饋一些友好的失敗通告到名為Message的標籤上。
這段代碼中的最大的竅門就是始終讓對象使用了三個不同的名稱。使用了一個Access檔案(MDB)作為資料來源並使用AccessDataSource控制項。但是使用了底層的SqlDataSource作為事件參數。最後,使用了普通的OLEDB異常集。很多錯誤都源於在所有的情況下都使用名為Access的ASP.NET 2.0對象。