数据源控件如何为数据绑定字段创建参数
更新:2007 年 11 月
当数据绑定控件(如 GridView、DetailsView 或 FormView 控件)与 ASP.NET 数据源控件共同使用时,数据绑定控件可根据数据绑定控件中的绑定字段向数据源控件传递参数名称和值。然后数据源控件会在参数集合中包含字段名称和值,以进行选择或更新操作。有关更多信息,请参见 对 SqlDataSource 控件使用参数 和 对 ObjectDataSource 控件使用参数。
传递给数据源控件的字典
数据绑定控件从数据源控件请求操作时,会传递一个或多个包含参数名称和值的 IDictionary 集合,这些参数名称和值供所请求的数据操作使用。字典中的名称/值对的值从子控件派生。例如,在更新操作中,数据绑定控件从以编辑模式显示的 TextBox 或 CheckBox 控件中读取参数值。名称/值对的名称来自于绑定到子控件的字段名称和 DataKeyNames 属性中指定的字段名称。对于更新或删除操作,数据绑定控件也可以传递包含数据记录原始值的字典。
使用以下 IDictionary 集合传递名称/值对:
Values 集合 为插入操作传递。包含新记录的名称/值对。Values 集合的字段名称和值来自于 InsertItemTemplate 中的子控件,或 DetailsView 控件(其 InsertVisible 属性设置为 true)中的绑定字段。
Keys 集合 为更新和删除操作传递。包含正被更新或删除的记录的主键或键。如果可在数据源对键字段进行修改,则 Keys 集合还会包含键字段的原始值。如果使用数据源控件中的数据对数据绑定控件进行填充,则在视图状态中维护该数据。在请求更新或删除操作时,Keys 集合由之前中视图状态中存储的值填充。如果数据绑定控件的 EnableViewState 属性设置为 false,则不会为更新或删除操作填充 Keys 集合。
NewValues 集合 为更新操作传递。包含具有更新项新值的名称/值对,其中包括可更新的键字段的新值。NewValues 集合的字段名称和值来自于 EditItemTemplate 中的子控件,或 DetailsView 控件(其 ReadOnly 属性设置为 false)中的绑定字段。
OldValues 集合 为更新或删除操作传递。包含要用于开放式并发检查的数据记录的原始值。(有关开放式并发检查的信息,请参见所用数据源控件的 ConflictDetection 属性。)OldValues 集合中不包含由 DataKeyNames 属性标识的键字段的值。键字段名称和值仅包含在 Keys 集合中。如果使用数据源控件中的数据对数据绑定控件进行填充,则在视图状态中维护该数据。在请求更新或删除操作时,将使用之前在视图状态中存储的值填充 OldValues 集合。如果数据绑定控件的 EnableViewState 属性设置为 false,则不会为更新或删除操作填充 OldValues 集合。
可以使用数据绑定控件事件为所请求的操作传递的参数访问所有这些集合。例如,在 GridView 控件的 RowUpdating 事件中,GridViewUpdateEventArgs 类提供对 NewValues 集合的访问。
参数名称
数据源控件会自动为 IDictionary 集合中传递的值创建参数。对于插入操作,数据源控件会使用 Values 集合内的名称/值对中的值填充其 InsertParameters 集合。对于更新操作,数据源控件会使用 Keys、NewValues 和 OldValues 集合内的名称/值对中的值填充其 UpdateParameters 集合。对于删除操作,数据源控件会使用 Keys 和 OldValues 集合内的名称/值对中的值填充其 DeleteParameters 集合。
默认情况下,不填充 OldValues 集合。仅在数据源控件的 ConflictDetection 属性设置为 CompareAllValues 时才对其进行填充。
对于更新或删除操作,默认情况下只创建当前绑定值的参数。如果必须同时访问当前值和原始绑定值(例如,要支持开放式并发检查),可以让数据源控件同时为当前值和原始值创建参数。为此,必须为将包含原始值的参数建立命名约定。这些原始值的参数的格式由 OldValuesParameterFormatString 属性确定。将 OldValuesParameterFormatString 属性设置为一个字符串。该字符串包含的“{0}”是该字段名称的占位符。例如,如果您使用的是 SqlDataSource 控件,并将 OldValuesParameterFormatString 属性设置为“old_{0}”,则原始值参数的名称将会解析为带“@old_”前缀的字段名称。(SqlDataSource 控件将“@”字符追加到所有参数名称的开头。)考虑对名为 LastModifiedDate 的字段执行更新操作。该字段的当前值传递到 Values 字典中,原始值传递到 OldValues 字典中。此时,将会创建名为 @LastModifiedDate 参数,用来传递当前值,同时会创建名为 @old\_LastModifiedDate 参数,用来传递原始值。此后,可以将这两个参数都包括在 SQL 语句中,以便区别该字段的当前值和原始值,如以下示例所示:
UPDATE Table1 SET LastModifiedDate = @LastModifiedDate
WHERE Key = @Key AND LastModifiedDate = @old_LastModifiedDate
不必直接访问名称/值 IDictionary 集合。可以简单地在 SQL 语句中包含自动生成的参数名称(如果数据源支持命名参数),或是使用 ObjectDataSource 控件访问的业务对象中的数据方法的参数名称。
也可以选择定义数据源控件的 UpdateParameters、InsertParameters 或 DeleteParameters 集合中的 Parameter 对象,以便自定义数据绑定控件传递的值。可以创建 Parameter 对象强类型化该值,或在传递 null 时指定一个默认值。
下面的代码示例演示一个绑定到 SqlDataSource 控件的 DetailsView 控件。SqlDataSource 控件的 InsertCommand、UpdateCommand 和 DeleteCommand 属性使用 SqlDataSource 控件自动生成的参数名称。将根据 Keys 和 NewValues 字典来填充这些参数值。由于默认情况下 ConflictDetection 属性设置为 ConflictOptions.OverwriteChanges,因此不使用 OldValues 字典。
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
Sub EmployeesDropDownList_OnSelectedIndexChanged(sender As Object, e As EventArgs)
EmployeeDetailsView.DataBind()
End Sub
Sub EmployeeDetailsView_ItemUpdated(sender As Object, e As DetailsViewUpdatedEventArgs)
EmployeesDropDownList.DataBind()
EmployeesDropDownList.SelectedValue = e.Keys("EmployeeID").ToString()
EmployeeDetailsView.DataBind()
End Sub
Sub EmployeeDetailsView_ItemDeleted(sender As Object, e As DetailsViewDeletedEventArgs)
EmployeesDropDownList.DataBind()
End Sub
Sub EmployeeDetailsSqlDataSource_OnInserted(sender As Object, e As SqlDataSourceStatusEventArgs)
Dim command As System.Data.Common.DbCommand = e.Command
EmployeesDropDownList.DataBind()
EmployeesDropDownList.SelectedValue = _
command.Parameters("@EmpID").Value.ToString()
EmployeeDetailsView.DataBind()
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">
<h3>Northwind Employees</h3>
<table cellspacing="10">
<tr>
<td valign="top">
<asp:DropDownList ID="EmployeesDropDownList"
DataSourceID="EmployeesSqlDataSource"
DataValueField="EmployeeID"
DataTextField="FullName"
AutoPostBack="True"
OnSelectedIndexChanged="EmployeesDropDownList_OnSelectedIndexChanged"
RunAt="Server" />
</td>
<td valign="top">
<asp:DetailsView ID="EmployeeDetailsView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateRows="false"
AutoGenerateInsertbutton="true"
AutoGenerateEditbutton="true"
AutoGenerateDeletebutton="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeDetailsView_ItemUpdated"
OnItemDeleted="EmployeeDetailsView_ItemDeleted"
RunAt="server">
<HeaderStyle backcolor="Navy"
forecolor="White"/>
<RowStyle backcolor="White"/>
<AlternatingRowStyle backcolor="LightGray"/>
<EditRowStyle backcolor="LightCyan"/>
<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisible="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:BoundField DataField="Address" HeaderText="Address"/>
<asp:BoundField DataField="City" HeaderText="City"/>
<asp:BoundField DataField="Region" HeaderText="Region"/>
<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>
</Fields>
</asp:DetailsView>
</td>
</tr>
</table>
<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Employees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:SqlDataSource>
<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Address, City, Region, PostalCode
FROM Employees WHERE EmployeeID = @EmpID"
InsertCommand="INSERT INTO Employees(LastName, FirstName, Address, City, Region, PostalCode)
VALUES (@LastName, @FirstName, @Address, @City, @Region, @PostalCode);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Address=@Address,
City=@City, Region=@Region, PostalCode=@PostalCode
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">
<SelectParameters>
<asp:ControlParameter ControlID="EmployeesDropDownList" PropertyName="SelectedValue"
Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>
<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</UpdateParameters>
<DeleteParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</DeleteParameters>
</asp:SqlDataSource>
</form>
</body>
</html>
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void EmployeesDropDownList_OnSelectedIndexChanged(Object sender, EventArgs e)
{
EmployeeDetailsView.DataBind();
}
void EmployeeDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e)
{
EmployeesDropDownList.DataBind();
EmployeesDropDownList.SelectedValue = e.Keys["EmployeeID"].ToString();
EmployeeDetailsView.DataBind();
}
void EmployeeDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e)
{
EmployeesDropDownList.DataBind();
}
void EmployeeDetailsSqlDataSource_OnInserted(Object sender, SqlDataSourceStatusEventArgs e)
{
System.Data.Common.DbCommand command = e.Command;
EmployeesDropDownList.DataBind();
EmployeesDropDownList.SelectedValue =
command.Parameters["@EmpID"].Value.ToString();
EmployeeDetailsView.DataBind();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">
<h3>Northwind Employees</h3>
<table cellspacing="10">
<tr>
<td valign="top">
<asp:DropDownList ID="EmployeesDropDownList"
DataSourceID="EmployeesSqlDataSource"
DataValueField="EmployeeID"
DataTextField="FullName"
AutoPostBack="True"
OnSelectedIndexChanged="EmployeesDropDownList_OnSelectedIndexChanged"
RunAt="Server" />
</td>
<td valign="top">
<asp:DetailsView ID="EmployeeDetailsView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateRows="false"
AutoGenerateInsertbutton="true"
AutoGenerateEditbutton="true"
AutoGenerateDeletebutton="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeDetailsView_ItemUpdated"
OnItemDeleted="EmployeeDetailsView_ItemDeleted"
RunAt="server">
<HeaderStyle backcolor="Navy"
forecolor="White"/>
<RowStyle backcolor="White"/>
<AlternatingRowStyle backcolor="LightGray"/>
<EditRowStyle backcolor="LightCyan"/>
<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisible="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:BoundField DataField="Address" HeaderText="Address"/>
<asp:BoundField DataField="City" HeaderText="City"/>
<asp:BoundField DataField="Region" HeaderText="Region"/>
<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>
</Fields>
</asp:DetailsView>
</td>
</tr>
</table>
<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Employees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:SqlDataSource>
<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Address, City, Region, PostalCode
FROM Employees WHERE EmployeeID = @EmpID"
InsertCommand="INSERT INTO Employees(LastName, FirstName, Address, City, Region, PostalCode)
VALUES (@LastName, @FirstName, @Address, @City, @Region, @PostalCode);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Address=@Address,
City=@City, Region=@Region, PostalCode=@PostalCode
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">
<SelectParameters>
<asp:ControlParameter ControlID="EmployeesDropDownList" PropertyName="SelectedValue"
Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>
<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</UpdateParameters>
<DeleteParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</DeleteParameters>
</asp:SqlDataSource>
</form>
</body>
</html>