在ASP.NET中使用SQL的IN操作
這篇文章將建立一列包含CheckBox控件的DataGrid,這個控件允許用戶對明細瀏覽進行多列選擇。如果沒有恢復對于動態SQL獲得該功能的一種方法,那么必須使用IN操作。
在文章的結尾,我們寫了一個SQL Server用戶自定義函數(UDF),為了將一個字符串分解成帶分隔符的子字符串。在這篇文章中,我們能看到這樣一個UDF如何派得上用場。我們將建立一個web表單,在此用戶可以通過選擇checkbox控件而選擇一些在DataGrid中的記錄。對這些被檢查的記錄的明細將會出現在表單中的另一個DataGrid中。這個表單像來如圖所示。
在下面顯示了我們用來建立表單的ASPX。注意:如何使用TemplateColumn和Checkbox控件增加DataGrid列。我們也使用DataGrid的DataKeyField屬性來告訴對象,在數據庫記錄的哪一個字段將會包含第一行的關鍵字標示符。
當表單加載初始化時,需要組裝頂端的DataGrid。代碼使用Enterprise Library來存取SQL Sever Northwind例子數據庫并且執行“SELECT EmployeeID,FirstName,LastName FROM Employees”這一語句。加載事件的代碼如下:
當用戶單擊“Orders”按鈕時,我們想顯示與數據庫中的那些與Employees相配并與Orders數據相關的第二個數據表格。這樣做的一種方法是建立動態的SQL并且使用所有EmployeeIDs所需的WHERE語句的OR條件。
第二個方法是使用WHERE語句的IN操作。IN操作將會一列表達式進行比較。例如,下列語句返回employee中IDS 7和4之間的信息。
在觀念上說,我愿意使用一個單一字符串參數來查詢所傳遞的IDs,然而,也許作為一個單字符串,不能對IN操作使用一個單一字符串參數。如果那樣,SQL語句會這樣“WHERE Employee IN (‘7,4’)”,并且數據庫因為EmployeeID屬于類型int—不屬于varchar類型而返回一個錯誤消息。
不過,我們使用文章中構造的split函數將字符串分離成不同的值。向split函數傳遞字符串‘7,4’,并且我們會得到與值4和7相對應的兩條記錄。選擇employees并且計算它們的定單總數的SQL查詢,將會如下:
使用以上查詢所需要的是必須建立和傳遞@employeeIDs參數。這個參數將是用逗號隔開的IDs列表。為了建立該字符串,為了弄明白行是否被用戶選擇,我們需要使用一個循環,這一循環以行數循環次數,并且檢查每一個checkbox控件。如果用戶選擇了行,通過從表的DataKeys屬性中(它被建立在ASPX文件中來指向EmployeeID字段)提取檢驗人,將關鍵字保存在employee中。
以上方法返回一個字符串,像“10,7,20”。對Orders按鈕單擊事件處理器將涉及這樣一個方法,將信息傳遞至SQL以得到employees和orders的列表,并且將其結果綁定在第二個DataGrid對象中。
在文章的結尾,我們寫了一個SQL Server用戶自定義函數(UDF),為了將一個字符串分解成帶分隔符的子字符串。在這篇文章中,我們能看到這樣一個UDF如何派得上用場。我們將建立一個web表單,在此用戶可以通過選擇checkbox控件而選擇一些在DataGrid中的記錄。對這些被檢查的記錄的明細將會出現在表單中的另一個DataGrid中。這個表單像來如圖所示。
在下面顯示了我們用來建立表單的ASPX。注意:如何使用TemplateColumn和Checkbox控件增加DataGrid列。我們也使用DataGrid的DataKeyField屬性來告訴對象,在數據庫記錄的哪一個字段將會包含第一行的關鍵字標示符。
| <form id="Form1" method="post" runat="server"> <asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False" DataKeyField="EmployeeID"> <Columns> <asp:TemplateColumn> <ItemTemplate> <asp:CheckBox runat="server" ID="EmployeeCheckBox" /> </ItemTemplate> </asp:TemplateColumn> <asp:TemplateColumn> <ItemTemplate> <%# DataBinder.Eval(Container.DataItem, "LastName") %>, <%# DataBinder.Eval(Container.DataItem, "FirstName") %> </ItemTemplate> </asp:TemplateColumn> </Columns> </asp:DataGrid> <hr> <asp:Button id="Orders" runat="server" Text="View Orders"></asp:Button> <hr> <asp:DataGrid ID="DataGrid2" Runat="server" AutoGenerateColumns="True" /> </form> |
當表單加載初始化時,需要組裝頂端的DataGrid。代碼使用Enterprise Library來存取SQL Sever Northwind例子數據庫并且執行“SELECT EmployeeID,FirstName,LastName FROM Employees”這一語句。加載事件的代碼如下:
| private void Page_Load(object sender, System.EventArgs e) { if(!Page.IsPostBack) { Database db = DatabaseFactory.CreateDatabase(); DBCommandWrapper dbCommandWrapper; using(dbCommandWrapper = db.GetSqlStringCommandWrapper(SELECT_EMPLOYEES)) { using (IDataReader dataReader = db.ExecuteReader(dbCommandWrapper)) { DataGrid1.DataSource = dataReader; DataGrid1.DataBind(); } } } } |
當用戶單擊“Orders”按鈕時,我們想顯示與數據庫中的那些與Employees相配并與Orders數據相關的第二個數據表格。這樣做的一種方法是建立動態的SQL并且使用所有EmployeeIDs所需的WHERE語句的OR條件。
第二個方法是使用WHERE語句的IN操作。IN操作將會一列表達式進行比較。例如,下列語句返回employee中IDS 7和4之間的信息。
| SELECT EmployeeID, FirstName, LastName FROM Employees WHERE EmployeeID IN (7, 4) |
在觀念上說,我愿意使用一個單一字符串參數來查詢所傳遞的IDs,然而,也許作為一個單字符串,不能對IN操作使用一個單一字符串參數。如果那樣,SQL語句會這樣“WHERE Employee IN (‘7,4’)”,并且數據庫因為EmployeeID屬于類型int—不屬于varchar類型而返回一個錯誤消息。
不過,我們使用文章中構造的split函數將字符串分離成不同的值。向split函數傳遞字符串‘7,4’,并且我們會得到與值4和7相對應的兩條記錄。選擇employees并且計算它們的定單總數的SQL查詢,將會如下:
| SELECT count(*) AS Orders, E.FirstName, E.LastName FROM Orders O INNER JOIN Employees E ON O.EmployeeID = E.EmployeeID WHERE E.EmployeeID IN(SELECT Value FROM fn_Split(@employeeIDs, ',')) GROUP BY FirstName, LastName ORDER BY count(*) DESC |
使用以上查詢所需要的是必須建立和傳遞@employeeIDs參數。這個參數將是用逗號隔開的IDs列表。為了建立該字符串,為了弄明白行是否被用戶選擇,我們需要使用一個循環,這一循環以行數循環次數,并且檢查每一個checkbox控件。如果用戶選擇了行,通過從表的DataKeys屬性中(它被建立在ASPX文件中來指向EmployeeID字段)提取檢驗人,將關鍵字保存在employee中。
| private string GetCheckedEmployeeIDs() { String delimiter = String.Empty; StringBuilder employeeIDs = new StringBuilder(); for(int i = 0; i < DataGrid1.Items.Count; i++) { CheckBox checkbox; checkbox = DataGrid1.Items[i].FindControl("EmployeeCheckBox") as CheckBox; if(checkbox != null && checkbox.Checked == true) { employeeIDs.Append(delimiter + DataGrid1.DataKeys[i].ToString()) ; delimiter = ","; } } return employeeIDs.ToString(); } |
以上方法返回一個字符串,像“10,7,20”。對Orders按鈕單擊事件處理器將涉及這樣一個方法,將信息傳遞至SQL以得到employees和orders的列表,并且將其結果綁定在第二個DataGrid對象中。
| private void Orders_Click(object sender, System.EventArgs e) { string employeeIDs = GetCheckedEmployeeIDs(); Database db = DatabaseFactory.CreateDatabase(); DBCommandWrapper dbCommandWrapper; using(dbCommandWrapper = db.GetSqlStringCommandWrapper(SELECT_ORDERS)) { dbCommandWrapper.AddInParameter("@employeeIDs", DbType.String, employeeIDs); using (IDataReader dataReader = db.ExecuteReader(dbCommandWrapper)) { DataGrid2.DataSource = dataReader; DataGrid2.DataBind(); } } } |