你可以处理Select、Update、Insert、Delete和Filter的事件,以验证并处 理传递给这些操作的参数值。为了达到这个目标,数据绑定的控件和数据源控件 都暴露了适当的事件。例如,在GridView的Updating事件中,你就可以看到Keys 、NewValues和OldValues字典中的参数名称和值,而它们将会被传递到数据源。 在数据源一端,你可以处理SqlDataSource的Updating事件,看到这些应用到下 层命令对象的参数,而这些命令将会执行以完成相关操作。类似的,你可以处理 ObjectDataSource的Updating事件来查看或改变参数字典,而这些字典将用于分 析UpdateMethod的适当操作。你可以使用这些事件来增加或删除字典或命令的参 数、改变它们的值、或者简单地验证参数的输入格式是否正确。
请注意:你尤其需要验证Filtering事件的参数输入,因为在它应用到相关的 DataView对象的FilterExpression(过滤器表达式)之前不会获得SQL编码 (encoded)。
下面的示例演示了处理多个数据控件的事件来枚举那些通过事件参数传递的 参数集合。请注意,这个示例把与OrderID主键字段相关联的绑定字段的 InsertVisible属性设置为假,这是因为在下层数据库中OrderID是一个标识列, 不应该传递给Insert操作(当插入发生的时候数据库自动地增加这个值)。同时 请注意,在DataKeyNames中,OrderID字段被标记为主键,因此这个字段的原始 值保留在数据绑定控件所传递的Keys字典中。用户输入控件的值都传递进 NewValues字典(除了那些标记了ReadOnly=false的字段)。非键字段的原始值 由数据绑定控件保留在OldValues字典中,以供传递给数据源。这些参数值都被 SqlDataSource按照NewValues、Keys和OldValues的次序附加到命令上,尽管在 默认情况下,当ConflictDetection被设置为OverwriteChanges的时候,数据源 不会附加OldValues。你可以在后面的"使用冲突检测"部分看到数据源是如何使 用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
你可以通过向数据源使用的参数集合添加静态的Parameter对象来改变 SqlDataSource附加到命令上的参数次序。SqlDataSource会根据这些参数对象的 次序来重新排列数据绑定控件所传递的参数。当数据源的ProviderName属性被设 置为System.Data.OleDb的时候,这种操作就有用处了,这是由于它不支持命名 (named)参数,因此附加到命令上的参数的次序必须与命令中的匿名参数占位 符('?')的次序相匹配。当我们使用命名参数的时候,参数的次序就是无关紧 要的。你可以指定Parameter对象的Type属性,确保在执行命令或方法之前,强 制数据绑定控件传递的值被转换为适当的数据类型。同样地,你还可以设置 Parameter的Size属性,规定SqlDataSource命令中DbParameter的位数大小(必 须用于输入/输出、输出和返回值参数)。
<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>
<asp:Parameter Name="OrderDate" Type="DateTime" />
<asp:Parameter Name="ShipCountry" Type="String" />
<asp:Parameter Name="OrderID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>