2011-09-06 67 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中描述了这一点。 –