使用參數和 SqlDataSource 控制項
更新:2007 年 11 月
SQL 陳述式和預存程序通常包含會在執行階段進行評估的參數。使用參數撰寫的 SQL 陳述式稱為參數型 SQL 陳述式。
當使用 SqlDataSource 控制項時,您可以指定使用參數的 SQL 查詢和陳述式。這可以根據在執行階段評估的值讀取和撰寫資料庫資訊,讓資料繫結案例更有彈性。您可以從各種來源取得參數值,包括 ASP.NET 應用程式變數、使用者識別和使用者選取的值。您可以使用參數提供資料擷取的搜尋準則、提供資料存放區中要插入、更新或刪除的值,以及提供排序、分頁和篩選的值。
使用參數
SqlDataSource 控制項就像所有的資料來源控制項,可以在執行階段接受輸入參數,並且在參數集合中加以管理。每個資料作業都有相關的參數集合。您可以在選取作業時使用 SelectParameters 集合,在更新作業時使用 UpdateParameters 集合等等。
您可以為每個參數指定名稱、類型、方向和預設值。從特定物件 (例如控制項、工作階段變數或使用者設定檔) 取得值的參數需要設定其他屬性。例如,ControlParameter 需要設定 ControlID 以識別取得參數值的控制項,並且設定 PropertyName 屬性指定包含參數值的屬性。如需詳細資訊,請參閱使用含有資料來源控制項的參數。
SqlDataSource 控制項也會根據支援自動更新、插入和刪除作業的資料繫結控制項 (例如 GridView 或 FormView 控制項) 所傳遞的值自動建立參數。如需詳細資訊,請參閱資料來源控制項如何建立資料繫結欄位的參數。
指定命令參數
當您使用 SqlDataSource 控制項時,可以將控制項的命令屬性設定為參數型 SQL 陳述式或預存程序名稱。如果您指定命令為一預存程序,就必須將命令的類型指定為 StoredProcedure。
參數名稱
SqlDataSource 控制項會將 ParameterPrefix 屬性的值加入所有參數名稱的開頭 (預設前置詞是 "@")。
如果是 GridView 之類的資料繫結控制項繫結至 SqlDataSource 控制項,在更新或刪除作業期間,資料繫結控制項會同時將目前和原始的記錄值傳遞至 SqlDataSource 控制項。目前的值會在 Values 字典中傳遞。原始值會在 Keys 或 OldValues 字典中傳遞。這些字典的內容,會附加到指定資料作業之基礎 DbCommand 物件的 Parameters 集合。
在 SqlDataSource 控制項的 SQL 命令中,可以使用命名慣例讓參數替代符號 (Placeholder) 符合傳遞至命令中的舊值。您可以藉由設定 SqlDataSource 控制項的 OldValuesParameterFormatString 屬性,建立替代符號名稱的格式。將 OldValuesParameterFormatString 屬性設定為包含 "{0}" 當做欄位名稱替代符號的字串。例如,如果您將 OldValuesParameterFormatString 屬性設定為 "old_{0}",原始實值參數的名稱將解析為使用 "@old_" 當做前置字元的欄位名稱。請考慮牽涉名為 LastModifiedDate 的欄位更新作業。欄位目前的值會在 Values 字典中傳遞,並且欄位的原始值會在 OldValues 字典中傳遞。還會建立名為 @LastModifiedDate 的參數傳遞目前的值,並且建立名為 @old\_LastModifiedDate 的參數傳遞原始值。然後可以在 SQL 陳述式中同時包含兩種參數,區分欄位目前的值和原始值,如同下列程式碼範例所示:
UPDATE Table1 SET LastModifiedDate = @LastModifiedDate
WHERE Key = @Key AND LastModifiedDate = @old_LastModifiedDate
在執行開放式並行存取 (Optimistic Concurrency) 檢查或使用能夠修改主索引鍵的資料來源時,必須要能夠在命令中分隔目前的值和原始值。
如需資料繫結控制項所傳遞字典的詳細資訊,請參閱資料來源控制項如何建立資料繫結欄位的參數。
搭配 SqlClient 提供者使用參數
根據預設,SqlDataSource 控制項會使用 System.Data.SqlClient 資料提供者將 SQL Server 當做資料來源運用。System.Data.SqlClient 提供者支援將具名參數當做替代符號,如同下列程式碼範例所示:
SELECT * FROM Employees WHERE LastName = @LastName
AND FirstName = @FirstName
使用具名參數時,在命令參數集合中指定參數的順序並不重要。然而,您必須確認在 SQL 命令中使用的參數名稱,能夠對應至相關集合中的參數名稱。
下列程式碼範例示範如何在使用 System.Data.SqlClient 提供者之 SqlDataSource 控制項的 SQL 命令中使用具名參數。
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @EmpID"
InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">
<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:sqlDataSource>
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @EmpID"
InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">
<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:sqlDataSource>
搭配 OleDb 和 Odbc 提供者使用參數
如果您連接至 OLE DB 或 ODBC 資料來源,可以設定 SqlDataSource 控制項搭配資料來源,以各自使用 System.Data.OleDb 或 System.Data.Odbc 提供者。System.Data.OleDb 和 System.Data.Odbc 提供者只支援由 "?" 字元所識別的位置參數,如同下列程式碼範例所示:
SELECT * FROM Employees WHERE LastName = ? AND FirstName = ?
當您搭配參數型 SQL 陳述式使用 System.Data.OleDb 和 System.Data.Odbc 提供者時,指定參數替代符號的順序,必須符合相關參數集合中的參數順序。您可以在相關資料作業的集合中明確指定參數順序以加以控制,例如相關 UpdateCommand 的 UpdateParameters 集合。當您明確建立參數的集合,而這個參數是從資料繫結控制項的傳遞值而自動建立時,明確建立的參數會覆寫自動產生的任何參數。這樣一來可以確認會使用您想要的順序傳遞參數。如果您呼叫會傳回值的預存程序,必須指定具有 ReturnValue 的 Direction 值之參數,做為命令參數集合中的第一個參數。
注意事項: |
---|
根據預設,依據資料繫結控制項繫結欄位的參數,會使用下列順序從參數字典中加入命令:Values、Keys、OldValues。刪除作業只會使用 Keys 字典。插入作業只會使用 Values 字典。如需資料繫結控制項所傳遞字典的詳細資訊,請參閱資料來源控制項如何建立資料繫結欄位的參數。 |
下列程式碼範例示範如何指定使用 System.Data.OleDb 提供者之 SqlDataSource 控制項的參數。參數會明確指定以確認在集合中的參數順序,符合 SQL 陳述式中的替代符號順序。
<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:TemplateField HeaderText="Birth Date">
<ItemTemplate>
<asp:Label ID="BirthDateLabel" Runat="Server"
Text='<%# Eval("BirthDate", "{0:d}") %>' />
</ItemTemplate>
<InsertItemTemplate>
<asp:Calendar ID="InsertBirthDateCalendar" Runat="Server"
SelectedDate='<%# Bind("BirthDate") %>' />
</InsertItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="EditBirthDateCalendar" Runat="Server"
VisibleDate='<%# Eval("BirthDate") %>'
SelectedDate='<%# Bind("BirthDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
</Fields>
<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:TemplateField HeaderText="Birth Date">
<ItemTemplate>
<asp:Label ID="BirthDateLabel" Runat="Server"
Text='<%# Eval("BirthDate", "{0:d}") %>' />
</ItemTemplate>
<InsertItemTemplate>
<asp:Calendar ID="InsertBirthDateCalendar" Runat="Server"
SelectedDate='<%# Bind("BirthDate") %>' />
</InsertItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="EditBirthDateCalendar" Runat="Server"
VisibleDate='<%# Eval("BirthDate") %>'
SelectedDate='<%# Bind("BirthDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
</Fields>