你可以处理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按照NewValuesKeys和OldValues的次序附加到命令上尽管在默认情况下当ConflictDetection被设置为OverwriteChanges的时候数据源不会附加OldValues你可以在后面的使用沖突检测部分看到数据源是如何使用OldValues的
<script runat=server>
Protected Sub EnumerateDictionary(ByVal dictionary As SystemCollectionsSpecializedIOrderedDictionary)
Dim entry As DictionaryEntry
For Each entry In dictionary
ResponseWrite( <b> & ServerHtmlEncode(entryKey) & </b>= & ServerHtmlEncode(entryValue) & ( & ServerHtmlEncode(entryValueGetType()Name) & )<br />)
Next
End Sub
Protected Sub EnumerateCommandParameters(ByVal command As SystemDataCommonDbCommand)
ResponseWrite(<br/>Parameter order in data source<br />)
Dim param As SystemDataCommonDbParameter
For Each param In commandParameters
ResponseWrite( <b> & ServerHtmlEncode(paramParameterName) & </b>= & ServerHtmlEncode(paramValue) & ( & ServerHtmlEncode(paramValueGetType()Name) & )<br />)
Next
End Sub
Protected Sub DetailsView_ItemUpdating(ByVal sender As Object ByVal e As SystemWebUIWebControlsDetailsViewUpdateEventArgs)
ResponseWrite(<br/>New Values passed from DetailsView<br />)
EnumerateDictionary(eNewValues)
ResponseWrite(<br/>Keys passed from DetailsView<br />)
EnumerateDictionary(eKeys)
ResponseWrite(<br/>Old Values passed from DetailsView<br />)
EnumerateDictionary(eOldValues)
End Sub
Protected Sub SqlDataSource_Updating(ByVal sender As Object ByVal e As SystemWebUIWebControlsSqlDataSourceCommandEventArgs)
EnumerateCommandParameters(eCommand)
eCancel = True
ResponseWrite(<br/>Update canceled)
End Sub
你可以通过向数据源使用的参数集合添加静态的Parameter对象来改变SqlDataSource附加到命令上的参数次序SqlDataSource会根据这些参数对象的次序来重新排列数据绑定控件所传递的参数当数据源的ProviderName属性被设置为SystemDataOleDb的时候这种操作就有用处了这是由于它不支持命名(named)参数因此附加到命令上的参数的次序必须与命令中的匿名参数占位符(?)的次序相匹配当我们使用命名参数的时候参数的次序就是无关紧要的你可以指定Parameter对象的Type属性确保在执行命令或方法之前强制数据绑定控件传递的值被转换为适当的数据类型同样地你还可以设置Parameter的Size属性规定SqlDataSource命令中DbParameter的位数大小(必须用于输入/输出输出和返回值参数)
<asp:SqlDataSource ConnectionString=<%$ ConnectionStrings:NorthwindOLEDB %> ID=SqlDataSource ProviderName=<%$ ConnectionStrings:NorthwindOLEDBProviderName %> runat=server SelectCommand=SELECT TOP [OrderID] [OrderDate] [ShipCountry] FROM [Orders] UpdateCommand=UPDATE [Orders] SET [OrderDate] = ? [ShipCountry] = ? WHERE [OrderID] = ? OnUpdating=SqlDataSource_Updating>
<UpdateParameters>
<asp:Parameter Name=OrderDate Type=DateTime />
<asp:Parameter Name=ShipCountry Type=String />
<asp:Parameter Name=OrderID Type=Int />
</UpdateParameters>
</asp:SqlDataSource>参数命名习惯要求新值根据数据源Select操作所选定的字段来命名我们也可以通过指定OldValuesParameterFormatString属性(例如指定为original_{})对Keys或OldValues中的参数进行重命名以便于把它们和NewValues参数区分开来你还可以通过处理适当的事件在数据源操作执行之前改变参数的值从而自定义参数名称例如如果SqlDataSource的更新操作与一个存储过程关联而该存储过程使用的参数名称与默认的命名习惯不同那么你就可以在该存储过程被调用之前在SqlDataSource的Updating事件修改参数名称下面的例子演示了这种技术
Protected Sub SqlDataSource_Updating(ByVal sender As Object ByVal e As SystemWebUIWebControlsSqlDataSourceCommandEventArgs)
eCommandParameters(@id)Value = eCommandParameters(@ContactID)Value
eCommandParameters(@name)Value = eCommandParameters(@ContactName)Value
eCommandParametersRemove(eCommandParameters(@ContactID))
eCommandParametersRemove(eCommandParameters(@ContactName))
End Sub
<asp:SqlDataSource ConnectionString=<%$ ConnectionStrings:Contacts %> ID=SqlDataSource runat=server SelectCommand=SELECT [ContactID] [ContactName] FROM [Contacts] UpdateCommand=UpdateContactName UpdateCommandType=StoredProcedure OnUpdating=SqlDataSource_Updating>
<UpdateParameters>
<asp:Parameter Name=id Type=Int />
<asp:Parameter Name=name Type=String />
</UpdateParameters>
</asp:SqlDataSource>
ObjectDataSource不依赖特定的参数次序而是简单地查找与参数名称相匹配的方法请注意ObjectDataSource不使用参数的类型或大小来分析方法重载它仅仅匹配参数名称因此如果你的业务对象中的两个方法拥有相同的名称和参数名称但是参数类型不同ObjectDataSource是无法把它们区分开的你可以在事件中改变ObjectDataSource参数的名称和值这点与上面的SqlDataSource示例类似但是如果你使用DataObjectTypeName给UpdateInsert和Delete操作指定一个特殊的数据对象类型就不可以修改参数名称了只能修改值如果你需要修改参数名称就不要使用DataObjectTypeName只能用代码在数据源事件中手动地构造适当的数据对象
上面我们用到的所有数据源参数都是Input参数用于把值传递到数据源操作中参数可以是双向的例如InputOutputOutput和ReturnValue参数你可以使用参数对象的Direction属性来指定参数的方向如果需要在数据源操作完成之后检索这些参数的值就需要处理适当的操作后(postoperation)事件(例如SelectedUpdatedInserted或Deleted事件)从传递到这些事件的事件参数中获取参数值SqlDataSourceStatusEventArgs拥有Command属性你可以使用它来获取返回值和输出参数如下面的例子所示请注意对于双向参数来说把SqlDataSource中的Parameter对象的Size属性设置为适当的值是非常重要的
<asp:SqlDataSource ID=
SqlDataSource
……>
<SelectParameters>
<asp:Parameter Direction=Output Name=TimeStamp Type=DateTime />
<asp:Parameter Direction=ReturnValue Name=ReturnValue Type=Int />
</SelectParameters>
</asp:SqlDataSource>
为了实现这个目标ObjectDataSourceStatusEventArgs类型支持OutputParameters集合和ReturnValue属性如下面一个例子所示请注意在这种情况下Update操作的返回值是用于检测操作所影响的行数的
Protected Sub ObjectDataSource_Selected(ByVal sender As Object ByVal e As ObjectDataSourceStatusEventArgs)
ResponseWrite(Record Count: & ServerHtmlEncode(eOutputParameters(totalCount)))
End Sub
Protected Sub ObjectDataSource_Updated(ByVal sender As Object ByVal e As ObjectDataSourceStatusEventArgs)
ResponseWrite(Rows Affected: & ServerHtmlEncode(eReturnValue) & <br/>)
End Sub
<asp:ObjectDataSource ID=ObjectDataSource ……>
<UpdateParameters>
<asp:Parameter Name=ContactName Type=String />
</UpdateParameters>
<SelectParameters>
<asp:Parameter Direction=Output Name=totalCount Type=Int />
</SelectParameters>
</asp:ObjectDataSource>
输出参数的另一种通常的用途是检索插入数据库的行的主键值而该主键列是一个标识列(在这种情况下在插入操作的参数中没有指定键值该键值是在插入操作发生时数据库服务器自动生成的)下面的例子演示了这种技术
Protected Sub SqlDataSource_Inserted(ByVal sender As Object ByVal e As SystemWebUIWebControlsSqlDataSourceStatusEventArgs)
ResponseWrite(Record Inserted: & ServerHtmlEncode(eCommandParameters(@ContactID)Value) & <br/>)
End Sub
<asp:SqlDataSource ID=SqlDataSource ……>
……
<InsertParameters>
<asp:Parameter Name=contactName Type=String />
<asp:Parameter Direction=Output Name=contactID Type=Int />
</InsertParameters>
</asp:SqlDataSource>