資料來源控制項如何建立資料繫結欄位的參數
更新:2007 年 11 月
當您搭配 ASP.NET 資料來源控制項,使用像是 GridView、DetailsView 或 FormView 的資料繫結控制項時,資料繫結控制項會根據其中的繫結欄位,將參數名稱和值傳遞給資料來源控制項。資料來源控制項就會在 Select 或 Update 作業的參數集合中包含這些欄位名稱和值。如需詳細資訊,請參閱使用參數和 SqlDataSource 控制項和使用參數和 ObjectDataSource 控制項。
傳遞給資料來源控制項的字典
當資料繫結控制項從資料來源控制項要求作業時,會傳遞一個或多個包含所要求資料作業之參數名稱和值的 IDictionary 集合。在字典中,名稱/值組的值是衍生自子控制項。例如在 Update 作業中,資料繫結控制項會從以編輯模式顯示的 TextBox 或 CheckBox 控制項讀取參數值。名稱/值組的名稱是從繫結至子控制項,以及 DataKeyNames 屬性中指定的欄位名稱取得。針對 Update 或 Delete 作業,資料繫結控制項可能也會傳遞包含資料錄原始值的字典。
名稱/值組會使用下列 IDictionary 集合傳遞:
Values 集合:Insert 作業時傳遞,包含新資料錄的名稱/值組。Values 集合的欄位名稱和值是從 InsertItemTemplate 中的子控制項,或是從 InsertVisible 屬性設定為 true 之 DetailsView 控制項中的繫結欄位取得。
Keys 集合:Update 和 Delete 作業時傳遞,包含主要索引鍵,或是要更新或刪除之資料錄的索引鍵。如果可以修改資料來源的索引鍵欄位,Keys 集合也包含索引鍵欄位的原始值。當您將資料來源控制項的資料填入資料繫結控制項時,就會在檢視狀態維護資料。當要求 Update 或 Delete 作業時,就會使用之前儲存在檢視狀態中的值填入 Keys 集合。如果資料繫結控制項的 EnableViewState 屬性設定為 false,Update 或 Delete 作業就不會填入 Keys 集合。
NewValues 集合:Update 作業時傳遞,包含使用更新項目新值的名稱/值組,其中包括可更新索引鍵欄位的新值。NewValues 集合的欄位名稱和值是從 EditItemTemplate 中的子控制項,或是 ReadOnly 屬性設定為 false 的 DetailsView 控制項繫結欄位取得。
OldValues 集合:Update 或 Delete 作業時傳遞,包含資料錄的原始值以便用來進行開放式並行存取檢查 (如需開放式並行存取檢查的資訊,請參閱所使用之資料來源控制項的 ConflictDetection 屬性)。DataKeyNames 屬性識別的索引鍵欄位值,並未包含在 OldValues 集合中。索引鍵欄名稱和值只包含在 Keys 集合中。當您將資料來源控制項的資料填入資料繫結控制項時,就會在檢視狀態維護資料。當要求 Update 或 Delete 作業時,就會使用之前儲存在檢視狀態中的值填入 OldValues 集合。如果資料繫結控制項的 EnableViewState 屬性設定為 false,Update 或 Delete 作業就不會填入 OldValues 集合。
您可以使用與要求作業的資料繫結控制項事件一起傳遞的引數,存取所有的集合。例如,在 GridView 控制項的 RowUpdating 事件中,GridViewUpdateEventArgs 類別會提供 NewValues 集合的存取。
參數名稱
資料來源控制項會自動為 IDictionary 集合中傳遞的值建立參數。資料來源控制項會針對 Insert 作業,使用來自 Values 集合中名稱/值組的值填入 InsertParameters 集合。資料來源控制項會針對 Update 作業,使用來自 Keys、NewValues 和 OldValues 集合中名稱/值組的值填入 UpdateParameters 集合。資料來源控制項會針對 Delete 作業,使用來自 Keys 和 OldValues 集合中名稱/值組的值填入 DeleteParameters 集合。
OldValues 集合依預設不會填入。只有在資料來源控制項的 ConflictDetection 屬性設定為 CompareAllValues 時才會填入。
對於更新或刪除作業而言,預設只會建立目前繫結值的參數。如果您需要存取目前和原始的繫結值 (例如,支援開放式並行存取 (Optimistic Concurrency) 檢查),則可以讓資料來源控制項建立目前和原始值的參數。若要這麼做,您必須替將包含原始值的參數建立命名規範。原始值的參數格式是由 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 >
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 >
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" >
<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 >
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 >
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" >
<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>