MIS2000 Lab. -- ASP.NET学习&分享 / ASP.NET案例精编(清华大学出版社)
您好,我来自台湾。很高兴与各位分享一些成果。希望对您有帮助。出版书籍是「ASP.NET案例精编 / 清华大学出版社」。

[习题]给初学者的范例,多重字段搜寻引擎 for GridView

http://www.dotblogs.com.tw/mis2000lab/archive/2008/04/25/3503.aspx

 

[习题]给初学者的范例,多重字段搜寻引擎 for GridView #2,兼论 SqlDataSource与SelectParameter的用法

http://www.dotblogs.com.tw/mis2000lab/archive/2008/04/25/3505.aspx

==========================================================

 

 

 

关于搜寻引擎的作法,我以前在 ASP.NET1.X版 就有提过,概念完全相同。

同时要搜寻多个字段,是有一点小诀窍的~

比较大的差异,是因为ASP.NET2.0新增的 SqlDataSource是一个精简版的数据存取功能,虽然比传统 ADO.NET更简便好用,但很多执行细节,也因为精灵带着我们一步一步走,而让初学者有点迷惘,甚至遇见问题无法修改。

 

 

 

 

 

我们用执行的图片,来介绍一下会出现哪种Bug ??

图片说明:多重字段的搜寻引擎,一旦搭配GridView「分页」功能,就出问题啦~

 

 

 

以下是我测试的一点小心得:

 

1. 首先,在Visual Studio 2005/2008开发工具里面,把 GridView拉进来,简单的设定一下。完成之后,SqlDataSource卷标里面的    「SQL指令」删除,这部份要放在后置程序代码,要自己手动撰写。   

    只留下这样子

<asp:SqlDataSource ID="SqlDataSource1" runat="server"

    ConnectionString="<%$ ConnectionStrings:testConnectionString%>">
</asp:SqlDataSource>

 

2. 多字段的搜寻引擎,搭配的SQL指令,必须是以「字符串」合并的方式来呈现,这样才能找得精准。这种作法很常见,网络上讨论大概都是这样作的,但市面上的书都不讲。

 

IF 字段一的值,「不是」空白 Then
    mySQLStr = " AND 字段一 like '%" & 字段一的值 &"%'"
End IF

 

IF 字段二的值,「不是」空白 Then
    mySQLStr = " AND 字段二 like '%" & 字段二的值 &"%'"
End IF      '----批注:以此类推。

 

SqlDataSource1.SelectCommand = "SELECT * FROM 资料表 WHERE 1=1 " + mySQLStr

 

请找一下我的旧文章----「进阶的搜寻引擎」,就是讲这一部份的程序,不难!

A.简单的搜寻引擎(单一字段搜寻)
B.进阶的搜寻引擎(多重字段搜寻)

 

 2010/3/5补充 --   黑暗执行绪的文章 , http://blog.darkthread.net/blogs/darkthreadtw/archive/2010/03/02/or-operator-in-sql.aspx

 

3. 上面都很简单。不过,一使用 GridView的「分页」功能,就会出问题。

解决的方法,就是SQL指令的部份,必须自己手动撰写。而且要很清楚这些SQL指令该放在「后置程序代码」的哪些地方......

 

 

作法满简单的,但初学者只会使用现成的控件来工作、只会用精灵来完成.....遇见状况就不知道该如何下手解决了。

这个问题,是让初学者必须开始「思考」ASP.NET背后是怎么运作的! ..........

 

 

 

 

请继续看下去:

为了解决这个问题,所以程序改写如下:

兼论 SqlDataSource与SelectParameter的用法

HTML画面

================================================================================

        Title:       <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
       <br />
       Summary:        <asp:TextBox ID="TextBox2"runat="server"></asp:TextBox><br />
       Article:        <asp:TextBox ID="TextBox3"runat="server"></asp:TextBox>

        <asp:ButtonID="Button1" runat="server" Text="Search~" /><br/>

       <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"CellPadding="4"
           DataKeyNames="id" Font-Size="X-Small" ForeColor="#333333"AllowPaging="True" PageSize="3"
            DataSourceID="SqlDataSource1">
           <FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White"/>
           <Columns>
               <asp:BoundField DataField="id" HeaderText="id" InsertVisible="False"ReadOnly="True" SortExpression="id" />
               <asp:BoundField DataField="test_time" HeaderText="test_time"SortExpression="test_time" DataFormatString="{0:yyyy/MM/dd}"HtmlEncode="False" />
               <asp:BoundField DataField="title" HeaderText="title" SortExpression="title">
                   <ItemStyle Font-Bold="True" Font-Size="Medium" ForeColor="#004000"/>
               </asp:BoundField>
               <asp:BoundField DataField="summary" HeaderText="summary"SortExpression="summary" />
               <asp:BoundField DataField="article" HeaderText="article"SortExpression="article" >
                   <ItemStyle Font-Size="X-Small" ForeColor="Purple" />
               </asp:BoundField>
               <asp:BoundField DataField="author" HeaderText="author" SortExpression="author"/>
           </Columns>
           <RowStyle BackColor="#E3EAEB" />
           <EditRowStyle BackColor="#7C6F57" />
           <SelectedRowStyle BackColor="#C5BBAF" Font-Bold="True" ForeColor="#333333"/>
           <PagerStyle BackColor="#666666" ForeColor="White" HorizontalAlign="Left"/>
           <HeaderStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White"/>
           <AlternatingRowStyle BackColor="White" />
           <EmptyDataTemplate>
               <strong><span style="font-size: 16pt; color: #ff0000">Sorry!!....NOTHING!!</span></strong>
           </EmptyDataTemplate>
       </asp:GridView>


        <asp:SqlDataSource ID="SqlDataSource1"runat="server" 

            ConnectionString="<%$ ConnectionStrings:testConnectionString%>">

            批注:  SqlDataSource里面是空的!!
        </asp:SqlDataSource>

 

 

 

以下是后置程序代码,

本文提供VB / C#两种版本给大家参考:

================================================================================

Code-Behind (for VB)

================================================================================

因为上方的HTML码里面,已经有一个「空的」 SqlDataSource,

里面也有数据库联机字符串了,所以底下的 DBInit()只需要拼凑、「组合」出适当的 SQL指令即可。

01     Sub myDBInit() myDBInit()
02         '== SqlDataSource精灵 自动产生的SQL指令,可以当作参考 ==
03         'SqlDataSource1.SelectCommand = "SELECT * FROM [test] WHERE (([title]LIKE '%' + @title + '%') AND ([summary] LIKE '%' + @summary + '%') AND ([article]LIKE '%' + @article + '%'))"
04
05         SqlDataSource1.SelectParameters.Clear()
06
07         '==以下是自己改写的「多重字段 搜寻引擎」,SQL指令的文字组合 ==
08         Dim mySQLstr As String = " 1=1 "
09
10         If TextBox1.Text <> ""Then
11             mySQLstr= mySQLstr + " AND ([title] LIKE '%' +@title + '%')"
12             '== 重点在此:参数必须写在IF判别式这里,不能一起写在后面。==
13             '== 否则,写在下面那区,所有出现的参数,不能留白! ==
14             SqlDataSource1.SelectParameters.Add("title", TextBox1.Text)
15         End If
16         If TextBox2.Text <> ""Then
17             mySQLstr= mySQLstr + " AND ([summary] LIKE '%'+ @summary + '%')"
18             SqlDataSource1.SelectParameters.Add("summary", TextBox2.Text)
19         End If
20         If TextBox3.Text <> ""Then
21             mySQLstr= mySQLstr + " AND ([article] LIKE '%'+ @article + '%')"
22             SqlDataSource1.SelectParameters.Add("article", TextBox3.Text)
23         End If
24
25         '============================================
26         '== 连结数据库的连接字符串 ConnectionString  ==
27         'SqlDataSource1.ConnectionString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings("testConnectionString").ConnectionString
28         '== 撰写SQL指令 ==
29         SqlDataSource1.SelectCommand= "SELECT * FROM [test] WHERE" + mySQLstr
30
31         Response.Write("<hr>您要搜寻哪些字段?SQL指令为  " & SqlDataSource1.SelectCommand& "<hr>")
32         '== 重点在此:参数必须写在上面的「每一个IF判别式」里面,不能一起写在这边。==
33         '== 否则,这里有出现的参数,就必须有「值」,不能留白! ==
34         'SqlDataSource1.SelectParameters.Add("title", TextBox1.Text)
35         'SqlDataSource1.SelectParameters.Add("summary", TextBox2.Text)
36         'SqlDataSource1.SelectParameters.Add("article", TextBox3.Text)
37
38         '== 执行SQL指令 .select() ==
39         'Dim dv As Data.DataView = SqlDataSource1.Select(New DataSourceSelectArguments)
40
41         'GridView1.DataSource = dv
42         'GridView1.DataBind()
43         '============================================
44     End Sub
45
46     Protected Sub Button1_Click() Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
47         If GridView1.PageIndex <>0 Then
48             '==如果不加上这行IF判别式,当我们看第四页时,
49             '==又输入新的条件,重新作搜寻。「新的」搜寻结果将会直接看见第四页!===
50             GridView1.PageIndex= 0
51         End If
52         myDBInit()
53     End Sub
54
55     Protected Sub GridView1_PageIndexChanging() Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs)Handles GridView1.PageIndexChanging
56         GridView1.PageIndex = e.NewPageIndex
57
58         Response.Write("目前位于第" & CInt(e.NewPageIndex.ToString()) + 1& "页<br>")
59         '== 必须把 GridView1 的 [EnableSortingAndPagingCallBack]属性关闭(=False),才会执行到这一行! ==
60     End Sub
61
62     Protected Sub GridView1_PageIndexChanged() Sub GridView1_PageIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.PageIndexChanged
63         myDBInit()
64     End Sub

 

================================================================================

Code-Behind (for C#)

================================================================================

因为上方的HTML码里面,已经有一个「空的」 SqlDataSource,

里面也有数据库联机字符串了,所以底下的 DBInit()只需要拼凑、「组合」出适当的 SQL指令即可。

01     protected void DBInit()
02     ...{
03         //== SqlDataSource精灵   自动产生的SQL指令,可以当作参考 ==
04         SqlDataSource1.SelectParameters.Clear();
05
06         //==以下是自己改写的「多重字段 搜寻引擎」,SQL指令的文字组合 ==
07         string mySQLstr = " 1=1 ";   //请注意, 1=1后面多一个空白!
08
09         if (TextBox1.Text != "")
10         ...{
11             mySQLstr= mySQLstr + " AND ([title] LIKE '%' +@title + '%')";
12             //== 重点在此:参数必须写在IF判别式这里,不能一起写在后面。==
13             SqlDataSource1.SelectParameters.Add("title", TextBox1.Text);
14         }
15             
16         if (TextBox2.Text != "")
17         ...{
18             mySQLstr= mySQLstr + " AND ([summary] LIKE '%'+ @summary + '%')";
19             SqlDataSource1.SelectParameters.Add("summary", TextBox2.Text);
20         }
21
22         if (TextBox3.Text != "")
23         ...{
24             mySQLstr= mySQLstr + " AND ([article] LIKE '%'+ @article + '%')";
25             SqlDataSource1.SelectParameters.Add("article", TextBox3.Text);
26         }
27
28         //============================================
29         //== SqlDataSource1 数据库的连接字符串 ConnectionString,
30         //== 已事先写在「HTML画面的设定」里面 ==
31         //============================================
32
33         //== 最后,合并成完整的SQL指令(搜寻引擎~专用) ==
34         SqlDataSource1.SelectCommand= "SELECT * FROM [test] WHERE" + mySQLstr;
35
36         //==================================================
37         //== 执行SQL指令 与 GridView1.DataBind()的部份,均已经事先写好
38         //==在「HTML画面的设定」上,也就是下面这一行,就通通搞定了。ASP.NET 真强!
39         //==<asp:GridView ID="GridView1" DataSourceID="SqlDataSource1">
40         //==================================================
41
42         Response.Write("<hr>您要搜寻哪些字段?SQL指令为  " + SqlDataSource1.SelectCommand+ "<hr>");
43         //== 重点在此:参数必须写在上面的「每一个IF判别式」里面,不能一起写在这边。==
44         //== 否则,这里有出现的参数,就必须有「值」,不能留白! ==
45         //SqlDataSource1.SelectParameters.Add("title", TextBox1.Text);
46         //SqlDataSource1.SelectParameters.Add("summary", TextBox2.Text);
47         //SqlDataSource1.SelectParameters.Add("article", TextBox3.Text);
48
49         //== 执行SQL指令 .select() ==
50         //DataView dv = SqlDataSource1.Select(new DataSourceSelectArguments);
51
52         //GridView1.DataSource = dv;
53         //GridView1.DataBind();
54         //============================================
55     }
56
57     protected void Button1_Click(object sender, EventArgs e)
58     ...{
59         if (Convert.ToInt32(GridView1.PageIndex)!= 0)
60         ...{
61            //==如果不加上这行IF判别式,假设当我们看第四页时,
62            //==又输入新的条件,重新作搜寻。「新的」搜寻结果将会直接看见 "第四页"!这个问题发生在这里,请看!===
63            GridView1.PageIndex= 0;
64         }
65
66         DBInit();
67     }
68
69     protected void  GridView1_PageIndexChanging(object sender, GridViewPageEventArgse)
70     ...{
71             GridView1.PageIndex= e.NewPageIndex;
72
73             Response.Write("目前位于第" + (Convert.ToInt32(e.NewPageIndex)+ 1) + "页<br>");
74             //== 把 GridView1 的 [EnableSortingAndPagingCallBack]属性关闭(=False),才会执行到这一行! ==
75     }
76
77     protected void  GridView1_PageIndexChanged(object sender, EventArgs e)
78     ...{
79         DBInit();
80     }

 

 

 

2010/6/7补充,关于这个搜寻引擎的范例(GridView ,共有两篇文章),

我撰写一篇完整的文章与您分享,请看:

[文章下载]网站内的搜寻引擎,单一字段与多重字段的搜寻(自己手写SqlDataSource与SelectParameter参数)

 

 

 

上面的程序代码,可能遭受数据隐码(SQLInjection)的攻击,请各位小心。


关于SQLInjection的介绍与解法,可以参考黄忠成老师的大作:

LINQ - 对付 SQL Injection "免费补洞策略"
一 连串的 Mass SQL Injection 攻击,让我们回忆起数年前的 SQL Injection 攻击,多年后的今天,我们仍深陷于同样的危机中,本文详述 SQL Injection 的历史、肇因、解决及侦测方法,更为读者们引介全新、更加安全的防堵 SQL Injection 策略。

 

posted on 2010-10-15 14:28  MIS2000 Lab.  阅读(633)  评论(0编辑  收藏  举报


ASP.NET案例精编——适用于VS 2005/2008(配光盘)
 

当当网购买 http://product.dangdang.com/product.aspx?product_id=20583373&ref=search-1-pub