日期:2010-12-13  浏览次数:20382 次

  你可以处理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>

  参数命名习惯要求新值根据数据源Select操作所选定的字段来命名。我们也可以通过指定OldValuesParameterFormatString属性(例如指定为"original_{0}")对Keys或OldValues中的参数进行重命名,以便于把它们和NewValues参数区分开来。你还可以通过处理适当的事件,在数据源操作执行之前改变参数的值,从而自定义参数名称。例如,如果SqlDataSource的更新操作与一个存储过程关联,而该存储过程使用的参数名称与默认的命名习惯不同,那么你就可以在该存储过程被调用之前,在SqlDataSource的Updating事件修改参数名称。下面的例子演示了这种技术。

Protected Sub