ASP.NET 2.0高級數(shù)據(jù)處理之使用參數(shù)

2010-08-28 10:50:27來源:西部e網(wǎng)作者:

  你可以處理Select、Update、Insert、Delete和Filter的事件,以驗證并處理傳遞給這些操作的參數(shù)值。為了達(dá)到這個目標(biāo),數(shù)據(jù)綁定的控件和數(shù)據(jù)源控件都暴露了適當(dāng)?shù)氖录。例如,在GridView的Updating事件中,你就可以看到Keys、NewValues和OldValues字典中的參數(shù)名稱和值,而它們將會被傳遞到數(shù)據(jù)源。在數(shù)據(jù)源一端,你可以處理SqlDataSource的Updating事件,看到這些應(yīng)用到下層命令對象的參數(shù),而這些命令將會執(zhí)行以完成相關(guān)操作。類似的,你可以處理ObjectDataSource的Updating事件來查看或改變參數(shù)字典,而這些字典將用于分析UpdateMethod的適當(dāng)操作。你可以使用這些事件來增加或刪除字典或命令的參數(shù)、改變它們的值、或者簡單地驗證參數(shù)的輸入格式是否正確。

  請注意:你尤其需要驗證Filtering事件的參數(shù)輸入,因為在它應(yīng)用到相關(guān)的DataView對象的FilterExpression(過濾器表達(dá)式)之前不會獲得SQL編碼(encoded)。

  下面的示例演示了處理多個數(shù)據(jù)控件的事件來枚舉那些通過事件參數(shù)傳遞的參數(shù)集合。請注意,這個示例把與OrderID主鍵字段相關(guān)聯(lián)的綁定字段的InsertVisible屬性設(shè)置為假,這是因為在下層數(shù)據(jù)庫中OrderID是一個標(biāo)識列,不應(yīng)該傳遞給Insert操作(當(dāng)插入發(fā)生的時候數(shù)據(jù)庫自動地增加這個值)。同時請注意,在DataKeyNames中,OrderID字段被標(biāo)記為主鍵,因此這個字段的原始值保留在數(shù)據(jù)綁定控件所傳遞的Keys字典中。用戶輸入控件的值都傳遞進(jìn)NewValues字典(除了那些標(biāo)記了ReadOnly=false的字段)。非鍵字段的原始值由數(shù)據(jù)綁定控件保留在OldValues字典中,以供傳遞給數(shù)據(jù)源。這些參數(shù)值都被SqlDataSource按照NewValues、Keys和OldValues的次序附加到命令上,盡管在默認(rèn)情況下,當(dāng)ConflictDetection被設(shè)置為OverwriteChanges的時候,數(shù)據(jù)源不會附加OldValues。你可以在后面的"使用沖突檢測"部分看到數(shù)據(jù)源是如何使用OldValues的。

<script runat="server">
Protected Sub EnumerateDictionary(ByVal dictionary As System.Collections.Specialized.IOrderedDictionary)
 Dim entry As DictionaryEntry
 For Each entry In dictionary
  Response.Write(" <b>" & Server.HtmlEncode(entry.Key) & "</b>=" & Server.HtmlEncode(entry.Value) & " (" & Server.HtmlEncode(entry.Value.GetType().Name) & ")<br />")
 Next
End Sub

Protected Sub EnumerateCommandParameters(ByVal command As System.Data.Common.DbCommand)
 Response.Write("<br/>Parameter order in data source...<br />")
 Dim param As System.Data.Common.DbParameter
 For Each param In command.Parameters
  Response.Write(" <b>" & Server.HtmlEncode(param.ParameterName) & "</b>=" & Server.HtmlEncode(param.Value) & " (" & Server.HtmlEncode(param.Value.GetType().Name) & ")<br />")
 Next
End Sub

Protected Sub DetailsView1_ItemUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewUpdateEventArgs)
 Response.Write("<br/>New Values passed from DetailsView...<br />")
 EnumerateDictionary(e.NewValues)
 Response.Write("<br/>Keys passed from DetailsView...<br />")
 EnumerateDictionary(e.Keys)
 
 Response.Write("<br/>Old Values passed from DetailsView...<br />")
 EnumerateDictionary(e.OldValues)
End Sub

Protected Sub SqlDataSource1_Updating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs)
 EnumerateCommandParameters(e.Command)
 e.Cancel = True
 Response.Write("<br/>Update canceled")
End Sub

  你可以通過向數(shù)據(jù)源使用的參數(shù)集合添加靜態(tài)的Parameter對象來改變SqlDataSource附加到命令上的參數(shù)次序。SqlDataSource會根據(jù)這些參數(shù)對象的次序來重新排列數(shù)據(jù)綁定控件所傳遞的參數(shù)。當(dāng)數(shù)據(jù)源的ProviderName屬性被設(shè)置為System.Data.OleDb的時候,這種操作就有用處了,這是由于它不支持命名(named)參數(shù),因此附加到命令上的參數(shù)的次序必須與命令中的匿名參數(shù)占位符('?')的次序相匹配。當(dāng)我們使用命名參數(shù)的時候,參數(shù)的次序就是無關(guān)緊要的。你可以指定Parameter對象的Type屬性,確保在執(zhí)行命令或方法之前,強制數(shù)據(jù)綁定控件傳遞的值被轉(zhuǎn)換為適當(dāng)?shù)臄?shù)據(jù)類型。同樣地,你還可以設(shè)置Parameter的Size屬性,規(guī)定SqlDataSource命令中DbParameter的位數(shù)大小(必須用于輸入/輸出、輸出和返回值參數(shù))。

<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:NorthwindOLEDB %>" ID="SqlDataSource1" ProviderName="<%$ ConnectionStrings:NorthwindOLEDB.ProviderName %>" runat="server" SelectCommand="SELECT TOP 10 [OrderID], [OrderDate], [ShipCountry] FROM [Orders]" UpdateCommand="UPDATE [Orders] SET [OrderDate] = ?, [ShipCountry] = ? WHERE [OrderID] = ?" OnUpdating="SqlDataSource1_Updating">
<UpdateParameters>
。糰sp:Parameter Name="OrderDate" Type="DateTime" />
 <asp:Parameter Name="ShipCountry" Type="String" />
。糰sp:Parameter Name="OrderID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>

  參數(shù)命名習(xí)慣要求新值根據(jù)數(shù)據(jù)源Select操作所選定的字段來命名。我們也可以通過指定OldValuesParameterFormatString屬性(例如指定為"original_{0}")對Keys或OldValues中的參數(shù)進(jìn)行重命名,以便于把它們和NewValues參數(shù)區(qū)分開來。你還可以通過處理適當(dāng)?shù)氖录,在?shù)據(jù)源操作執(zhí)行之前改變參數(shù)的值,從而自定義參數(shù)名稱。例如,如果SqlDataSource的更新操作與一個存儲過程關(guān)聯(lián),而該存儲過程使用的參數(shù)名稱與默認(rèn)的命名習(xí)慣不同,那么你就可以在該存儲過程被調(diào)用之前,在SqlDataSource的Updating事件修改參數(shù)名稱。下面的例子演示了這種技術(shù)。

Protected Sub SqlDataSource1_Updating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs)
 e.Command.Parameters("@id").Value = e.Command.Parameters("@ContactID").Value
 e.Command.Parameters("@name").Value = e.Command.Parameters("@ContactName").Value
 e.Command.Parameters.Remove(e.Command.Parameters("@ContactID"))
 e.Command.Parameters.Remove(e.Command.Parameters("@ContactName"))
End Sub

<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:Contacts %>" ID="SqlDataSource1" runat="server" SelectCommand="SELECT [ContactID], [ContactName] FROM [Contacts]" UpdateCommand="UpdateContactName" UpdateCommandType="StoredProcedure" OnUpdating="SqlDataSource1_Updating">
<UpdateParameters>
 <asp:Parameter Name="id" Type="Int32" />
。糰sp:Parameter Name="name" Type="String" />
</UpdateParameters>
</asp:SqlDataSource>

  ObjectDataSource不依賴特定的參數(shù)次序,而是簡單地查找與參數(shù)名稱相匹配的方法。請注意,ObjectDataSource不使用參數(shù)的類型或大小來分析方法重載,它僅僅匹配參數(shù)名稱,因此,如果你的業(yè)務(wù)對象中的兩個方法擁有相同的名稱和參數(shù)名稱,但是參數(shù)類型不同,ObjectDataSource是無法把它們區(qū)分開的。你可以在事件中改變ObjectDataSource參數(shù)的名稱和值,這點與上面的SqlDataSource示例類似。但是,如果你使用DataObjectTypeName給Update、Insert和Delete操作指定一個特殊的數(shù)據(jù)對象類型,就不可以修改參數(shù)名稱了--只能修改值。如果你需要修改參數(shù)名稱,就不要使用DataObjectTypeName,只能用代碼在數(shù)據(jù)源事件中手動地構(gòu)造適當(dāng)?shù)臄?shù)據(jù)對象。

  上面我們用到的所有數(shù)據(jù)源參數(shù)都是Input參數(shù),用于把值傳遞到數(shù)據(jù)源操作中。參數(shù)可以是雙向的,例如InputOutput、Output和ReturnValue參數(shù)。你可以使用參數(shù)對象的Direction屬性來指定參數(shù)的方向。如果需要在數(shù)據(jù)源操作完成之后檢索這些參數(shù)的值,就需要處理適當(dāng)?shù)牟僮骱螅╬ost-operation)事件(例如Selected、Updated、Inserted或Deleted事件),從傳遞到這些事件的事件參數(shù)中獲取參數(shù)值。SqlDataSourceStatusEventArgs擁有Command屬性,你可以使用它來獲取返回值和輸出參數(shù),如下面的例子所示。請注意,對于雙向參數(shù)來說,把SqlDataSource中的Parameter對象的Size屬性設(shè)置為適當(dāng)?shù)闹凳欠浅V匾摹?/P>

<asp:SqlDataSource ID="SqlDataSource1" ……>
<SelectParameters>
。糰sp:Parameter Direction="Output" Name="TimeStamp" Type="DateTime" />
。糰sp:Parameter Direction="ReturnValue" Name="ReturnValue" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>

  為了實現(xiàn)這個目標(biāo),ObjectDataSourceStatusEventArgs類型支持OutputParameters集合和ReturnValue屬性,如下面一個例子所示。請注意,在這種情況下,Update操作的返回值是用于檢測操作所影響的行數(shù)的。

Protected Sub ObjectDataSource1_Selected(ByVal sender As Object, ByVal e As ObjectDataSourceStatusEventArgs)
 Response.Write("Record Count: " & Server.HtmlEncode(e.OutputParameters("totalCount")))
End Sub

Protected Sub ObjectDataSource1_Updated(ByVal sender As Object, ByVal e As ObjectDataSourceStatusEventArgs)
 Response.Write("Rows Affected: " & Server.HtmlEncode(e.ReturnValue) & "<br/>")
End Sub

<asp:ObjectDataSource ID="ObjectDataSource1" ……>
 <UpdateParameters>
 。糰sp:Parameter Name="ContactName" Type="String" />
。/UpdateParameters>
。糞electParameters>
  <asp:Parameter Direction="Output" Name="totalCount" Type="Int32" />
。/SelectParameters>
</asp:ObjectDataSource>

  輸出參數(shù)的另一種通常的用途是檢索插入數(shù)據(jù)庫的行的主鍵值,而該主鍵列是一個標(biāo)識列(在這種情況下,在插入操作的參數(shù)中沒有指定鍵值,該鍵值是在插入操作發(fā)生時,數(shù)據(jù)庫服務(wù)器自動生成的)。下面的例子演示了這種技術(shù)。

Protected Sub SqlDataSource1_Inserted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs)
 Response.Write("Record Inserted: " & Server.HtmlEncode(e.Command.Parameters("@ContactID").Value) & "<br/>")
End Sub

<asp:SqlDataSource ID="SqlDataSource1" ……>
 ……
。糏nsertParameters>
  <asp:Parameter Name="contactName" Type="String" />
 。糰sp:Parameter Direction="Output" Name="contactID" Type="Int32" />
。/InsertParameters>
</asp:SqlDataSource>

關(guān)鍵詞:ASP.NET

贊助商鏈接: