2011-09-06 84 views
2

我有一個搜索引擎,應該搜索產品的描述,然後將顯示的產品列表中有用戶正在尋找的任何單詞或短語的東西。我還沒有爲使用描述的產品做出任何列表。ASP.net VB搜索引擎

我只需要弄清楚爲什麼我的SELECT語句沒有做任何事情。它可以是For Each循環。

這是我有:

Public Function GetDescriptions(ByVal prefixText As String, ByVal count As Integer) As String() 
    Dim MarketingSql As String = "Select MarketingID, MarketingType, MarketingData FROM Marketing WHERE MarketingType = 2 AND MarketingData LIKE '%" & prefixText & "%'" 
    Dim sqlConn As New SqlConnection 
    sqlConn.Open() 
    Dim myCommand As New SqlCommand(MarketingSql, sqlConn) 
    Dim myReader As SqlDataReader = myCommand.ExecuteReader() 
    Dim myTable As New DataTable 
    myTable.TableName = "DescriptionSearch" 
    myTable.Load(myReader) 
    sqlConn.Close() 
    Dim items As String() = New String(myTable.Rows.Count - 1) {} 
    Dim i As Integer = 0 
    For Each dr As DataRow In myTable.Rows 
     items.SetValue(dr("MarketingData").ToString(), i) 
     i += 1 
    Next 
    Return items 
End Function 


<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
<script type="text/javascript"> 
function AutoCompleteClientMethod(source, eventArgs) { 
    var value = eventArgs.get_value(); 
    window.location = ("/Product/Default.aspx?id=" + value) 
} 
</script> 
</asp:Content> 
<asp:Content ID="Content2" ContentPlaceHolderID="body" Runat="Server"> 
    <asp:ScriptManager ID="ScriptManager1" runat="server"> 
    <Services> 
     <asp:ServiceReference Path="DescriptionSearch.asmx" /> 
    </Services> 
</asp:ScriptManager> 
    <asp:TextBox ID="Search" runat="server" AutoComplete="off"></asp:TextBox> 
    <asp:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server" TargetControlID="Search" ServicePath="~/DescriptionSearch.asmx" ServiceMethod="GetDescriptions" MinimumPrefixLength="1" CompletionSetCount="255" EnableCaching="true" OnClientItemSelected="AutoCompleteClientMethod"> 
    </asp:AutoCompleteExtender> 
</asp:Content> 

回答

0

這是如何爲項目更新WebService。現在它工作得很好。

<WebMethod()> _ 
Public Function GetDescriptions(ByVal prefixText As String, ByVal count As Integer) 
As String() 
    Dim MarketingSql As String = "Select DISTINCT p.ProductID, p.ProductName 
FROM Product p 
INNER JOIN Marketing m ON p.ProductID = m.ProductID 
INNER JOIN Picklist k ON k.PicklistID = m.MarketingData 
WHERE m.MarketingTypeID = 2 AND k.Data LIKE '%' & @prefixText & '%' 
ORDER BY p.ProductName ASC" 
    Using sqlConn As New SqlConnection 
     (System.Configuration.ConfigurationManager.ConnectionStrings 
     ("LocalSqlServer").ConnectionString) 
    sqlConn.Open() 
    Dim myCommand As New SqlCommand(MarketingSql, sqlConn) 
    myCommand.Parameters.Add("@prefixText", SqlDbType.VarChar, 50).Value = prefixText 
    Dim myReader As SqlDataReader = myCommand.ExecuteReader() 
    Dim myTable As New DataTable 
    myTable.TableName = "DescriptionSearch" 
    myTable.Load(myReader) 
    sqlConn.Close() 
    Dim items As String() = New String(myTable.Rows.Count - 1) {} 
    Dim i As Integer = 0 
    For Each dr As DataRow In myTable.Rows 
     Dim id As String = dr("ProductID").ToString() 
     Dim name As String = dr("ProductName").ToString() 
     Dim item As String = AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(name, id) 
     items.SetValue(item, i) 
     i += 1 
    Next 
    Return items 
    End Using 
End Function 
+0

謝謝@JoelCoehoorn幫助我解決注射問題。 – jlg

3

馬上蝙蝠我看到三個問題與您的代碼:

  1. 正如你所說,你的代碼是容易受到SQL注入。你把這個活下去了,任何關心嘗試的人都會完全擁有你的數據庫。這並不困難。 「首先得到它」戰略是一個完全錯誤的方法來解決這個問題。像這樣的代碼常常會導致生產。
  2. 您正在使用LIKE運算符搜索冗長的文本列。這會吸引你的數據庫性能。這是全文索引和CONTAINS函數的絕佳選擇。在搜索時間方面,這將是晝夜。
  3. 您並不總是關閉您的數據庫連接。如果拋出異常,您將泄漏打開的連接對象,這最終可能會導致對您的數據庫實施有效的拒絕服務攻擊,這源於您自己的應用程序。數據庫連接必須始終將封裝在try/finally塊中。

而這只是冰山一角,從單純的掠奪中收集。我甚至還沒有開始深入閱讀代碼。


下面是一個更新(晚了,我知道)的基礎上,自我接受的答案來解決SQL注入的問題:

<WebMethod()> _ 
Public Function GetDescriptions(ByVal prefixText As String, ByVal count As Integer) 
As List(Of String) 
    Dim MarketingSql As String = "Select DISTINCT p.ProductID, p.ProductName 
     FROM Product p 
     INNER JOIN Marketing m ON p.ProductID = m.ProductID 
     INNER JOIN Picklist k ON k.PicklistID = m.MarketingData 
     WHERE m.MarketingTypeID = 2 AND k.Data LIKE '%' + @prefixText + '%' 
     ORDER BY p.ProductName ASC" 

    Using sqlConn As New SqlConnection 
     (System.Configuration.ConfigurationManager.ConnectionStrings 
     ("LocalSqlServer").ConnectionString), _ 
      myCommand As New SqlCommand(MarketingSql, sqlConn) 

     myCommand.Parameters.Add("@prefixText", SqlDbTypes.VarChar, 50).Value = prefixText 
     sqlConn.Open() 
     Using myReader As SqlDataReader = myCommand.ExecuteReader() 
      While myReader.Read() 
       Dim id As String = myReader("ProductID").ToString() 
       Dim name As String = myReader("ProductName").ToString() 
       items.Add(AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(name, id)) 
      End While 
     End Using 
    End Using 
    Return items 
End Function 
+0

爲了我自己的安心,你從哪裏畢業? – NickHeidke

+0

@尼克 - 剛纔看到您的評論。我去了哈丁大學。 –

+0

@Joel lol他問我,但我刪除了我的評論,因爲我希望版主會刪除這篇文章,因爲我必須自己回答。 – jlg

-1

除了喬爾的意見,你真的真的需要NEVER在你的代碼中放置Select語句(即使在測試中)...永遠。始終使用存儲過程。現在我所需要做的就是讀取web.config文件(假設您沒有花時間對其進行加密),讀取連接,並且可以完全訪問所有數據。

+0

參數化查詢也可以創造奇蹟。這是一種可怕的學習方式 - 詢問你的學校爲什麼你比教師更瞭解。 – adamcodes

+0

存儲過程不是唯一的選擇。有很多選擇,特別是在OR/Ms(如LINQ和NHibernate)方面工作正常,無需存儲過程。至於現在比上學時更多功課的問題,歡迎來到技術世界。你必須不斷學習新的東西才能生存。 –

+0

此外,請隨時查看我的網站上使用LINQ的搜索實現,我在http://www.thinqlinq.com/Default/Dynamically-extending-LINQ-queryies-without-building-expression-trees.aspx中描述了這一點。 –