[ASP.net Web Form] 不用撰寫後置程式碼的多欄位查詢撈資料

[ASP.net Web Form] 不用撰寫後置程式碼的多欄位查詢撈資料

最近在日本MSDN看到有人討論

然後大陸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>


但執行後會發現網頁原始碼

image

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>


如此一來就都不用寫後置程式碼做出多數欄位查詢的效果
第一次執行畫面:(撈全部資料)

image

選擇下拉選單:

image

再篩選CategoryName:

image

還原下拉選單All,做CategoryName的查詢:

image

因為中文版資料庫安裝時預設定序是不分大小寫的,所以All可以輸入all,再按查詢,就又是撈全部的資料

image

而且因為是傳參數查詢,所以可防SQL Injection,(下圖撈不到資料)

image

 

2011.7.20

TerryChuang網友讓小弟學到一課
只要
<SelectParameters>
              <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中為空字串時,就可以撈全部資料了