[ASP.net Web Form] 不用撰寫後置程式碼的多欄位查詢撈資料
最近在日本MSDN看到有人討論
所以這邊紀錄一下吧
這樣寫的好處是在 Page_Load事件、查詢按鈕Click事件、GridView分頁事件,不用再各別處理撈資料,省得打字
但代價就是 Or 條件串太多,可能導致查詢效能不彰
	
	至於撰寫技巧就如同之前提過的文章:[C#/Java] 不用動態組SQL字串的查詢程式碼
And ( ( 欄位變數 = 欄位變數預設值 ) Or ( Table欄位 = 欄位變數) )
所以請注意以下SqlDataSource的Select語句
<%@  Page Debug="true" Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default"  %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
      <div>
          <asp:SqlDataSource runat="server" ID="sds_Categories" 
              ConnectionString="<%$ ConnectionStrings:ConnectionString %>" 
              SelectCommand="
              SELECT [CategoryID], [CategoryName], [Description] FROM [Categories] Where ((@CategoryID = -1) Or (CategoryID = @CategoryID))
              And ((@CategoryName ='') Or (CategoryName Like '%' + @CategoryName +'%'))" >
              <SelectParameters>
              <asp:ControlParameter ControlID="ddl_Categories" PropertyName="SelectedValue" Name="CategoryID"  />
              <asp:ControlParameter ControlID="txt_CategoryName" PropertyName="Text" Name="CategoryName"    />
              </SelectParameters>
             </asp:SqlDataSource>
              CategoryID:
          <asp:DropDownList ID="ddl_Categories" runat="server">
              <asp:ListItem Text="All" Value="-1" />
              <asp:ListItem Text="1" Value="1" />
              <asp:ListItem Text="2" Value="2" />
              <asp:ListItem Text="3" Value="3" />
              <asp:ListItem Text="4" Value="4" />
              <asp:ListItem Text="5" Value="5" />
              <asp:ListItem Text="6" Value="6" />
              <asp:ListItem Text="7" Value="7" />
              <asp:ListItem Text="8" Value="8" />
          </asp:DropDownList>
              CategoryName:<asp:TextBox runat="server" ID="txt_CategoryName" Text="" /><br />          
          <asp:Button Text="查詢" ID="btn_Query" runat="server"  />
      </div>
      <div>
          <asp:GridView runat="server" ID="gv_table" DataSourceID="sds_Categories" 
              AutoGenerateColumns="False" DataKeyNames="CategoryID" >
              <Columns>
                  <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" 
                      InsertVisible="False" ReadOnly="True" SortExpression="CategoryID" />
                  <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" 
                      SortExpression="CategoryName" />
                  <asp:BoundField DataField="Description" HeaderText="Description" 
                      SortExpression="Description" />
              </Columns>
          </asp:GridView>
      
      </div>
    </form>
</body>
</html>
但執行後會發現網頁原始碼
	
TextBox Server Control,如果Text=””在呈現出HTML時,是不會加上Value的Attribute
所以導致網頁第一次執行沒有撈全部的資料
看了一下日本那邊的討論,折衷的辦法就是給Text=”All”
然後再改寫SqlDataSource的SelectCommand
<%@  Page Debug="true" Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default"  %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
      <div>
          <asp:SqlDataSource runat="server" ID="sds_Categories" 
              ConnectionString="<%$ ConnectionStrings:ConnectionString %>" 
              SelectCommand="
              SELECT [CategoryID], [CategoryName], [Description] FROM [Categories] Where ((@CategoryID = -1) Or (CategoryID = @CategoryID))
              And ((@CategoryName ='All') Or (CategoryName Like '%' + @CategoryName +'%'))" >
              <SelectParameters>
              <asp:ControlParameter ControlID="ddl_Categories" PropertyName="SelectedValue" Name="CategoryID"  />
              <asp:ControlParameter ControlID="txt_CategoryName" PropertyName="Text" Name="CategoryName"    />
              </SelectParameters>
             </asp:SqlDataSource>
              CategoryID:
          <asp:DropDownList ID="ddl_Categories" runat="server">
              <asp:ListItem Text="All" Value="-1" />
              <asp:ListItem Text="1" Value="1" />
              <asp:ListItem Text="2" Value="2" />
              <asp:ListItem Text="3" Value="3" />
              <asp:ListItem Text="4" Value="4" />
              <asp:ListItem Text="5" Value="5" />
              <asp:ListItem Text="6" Value="6" />
              <asp:ListItem Text="7" Value="7" />
              <asp:ListItem Text="8" Value="8" />
          </asp:DropDownList>
              CategoryName:<asp:TextBox runat="server" ID="txt_CategoryName" Text="All" /><br />
          <asp:Button Text="查詢"  ID="btn_Query" runat="server"  />
      </div>
      <div>
          <asp:GridView runat="server" ID="gv_table" DataSourceID="sds_Categories" 
              AutoGenerateColumns="False" DataKeyNames="CategoryID" >
              <Columns>
                  <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" 
                      InsertVisible="False" ReadOnly="True" SortExpression="CategoryID" />
                  <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" 
                      SortExpression="CategoryName" />
                  <asp:BoundField DataField="Description" HeaderText="Description" 
                      SortExpression="Description" />
              </Columns>
          </asp:GridView>
      
      </div>
    </form>
</body>
</html>
	如此一來就都不用寫後置程式碼做出多數欄位查詢的效果
	第一次執行畫面:(撈全部資料)
	
選擇下拉選單:
	
再篩選CategoryName:
	
還原下拉選單All,做CategoryName的查詢:
	
因為中文版資料庫安裝時預設定序是不分大小寫的,所以All可以輸入all,再按查詢,就又是撈全部的資料
	
而且因為是傳參數查詢,所以可防SQL Injection,(下圖撈不到資料)
	
2011.7.20
<asp:ControlParameter ControlID="ddl_Categories" PropertyName="SelectedValue" Name="CategoryID" />
<asp:ControlParameter ControlID="txt_CategoryName" PropertyName="Text" Name="CategoryName" ConvertEmptyStringToNull="false" />
</SelectParameters>
ConvertEmptyStringToNull="false"
這樣就可以
	 SELECT [CategoryID], [CategoryName], [Description] FROM [Categories] Where ((@CategoryID = -1) Or (CategoryID = @CategoryID))
	              And ((@CategoryName ='') Or (CategoryName Like '%' + @CategoryName +'%'))
如此一來,在TextBox中為空字串時,就可以撈全部資料了