2011-12-23 4 views
0

В настоящее время я разрабатываю веб-приложение, которое будет иметь форму поиска Autocomplete, результаты обновляются из базы данных Sql. Вся «функциональность» работает, за исключением одной вещи. Клиент вызывает C# Webservice, который собирается вернуть массив клиенту. Дело в том. Список клиентов показывает одинаковые результаты размножения. Таким образом, если только один результат соответствует базе данных, клиент показывает, что это соответствует 20-25 раз в вертикальном списке. Я не знаю, как это решить, пожалуйста, помогите.Ошибка поиска в автозаполнении

C# Webservice:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Services; 
using System.Data.SqlClient; 

namespace WebApplication6 
{ 

public class searchResult 
{ 
    public string Title; 
    public string img; 
    public string href; 
} 

/// <summary> 
/// Summary description for WebService 
/// </summary> 
[WebService(Namespace = "http://tempuri.org/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
[System.ComponentModel.ToolboxItem(false)] 
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
[System.Web.Script.Services.ScriptService] 
[System.Web.Script.Services.GenerateScriptType(typeof(searchResult))] 
public class WebService : System.Web.Services.WebService 
{ 

    [WebMethod] 
    public string HelloWorld() 
    { 
     return "Hello World"; 
    } 

    [WebMethod] 
    public searchResult[] Search(string txtSearch) 
    { 
     //Semuler to slow internet connection 
     //System.Threading.Thread.Sleep(2000); 

     //Declare collection of searchResult 
     List<searchResult> resultList = new List<searchResult>(); 

     string constr = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; ; 
     SqlConnection con = new SqlConnection(constr); 
     SqlCommand cmd = con.CreateCommand(); 

     cmd.CommandText = "SELECT * FROM [DriverInfo], [Teams], [Tracks] WHERE UserName LIKE '" + txtSearch + "%' OR TeamName LIKE '" + txtSearch + "%' OR TrackName LIKE '" + txtSearch + "%'"; 
     try 
     { 
      con.Open(); 

      SqlDataReader dr = cmd.ExecuteReader(); 
      while (dr.Read()) 
      { 
       searchResult DriverResult = new searchResult(); 
       DriverResult.Title = dr["UserName"].ToString(); 
       DriverResult.img = "driver.png"; 
       DriverResult.href = dr["UserId"].ToString(); 

       if (DriverResult.Title.ToLower().Contains(txtSearch.ToLower())) 
       { 
        resultList.Add(DriverResult); 
       } 

       searchResult TeamResult = new searchResult(); 
       TeamResult.Title = dr["TeamName"].ToString(); 
       TeamResult.img = "team.png"; 
       TeamResult.href = dr["Id"].ToString(); 

       if (TeamResult.Title.ToLower().Contains(txtSearch.ToLower())) 
       { 
        resultList.Add(TeamResult); 
       } 

       searchResult TrackResult = new searchResult(); 
       TrackResult.Title = dr["TrackName"].ToString(); 
       TrackResult.img = "track.png"; 
       TrackResult.href = dr["TrackId"].ToString(); 

       if (TrackResult.Title.ToLower().Contains(txtSearch.ToLower())) 
       { 
        resultList.Add(TrackResult); 
       } 
      } 
      con.Close(); 
      return resultList.ToArray(); 
     } 
     catch 
     { 
      return null; 
     } 

    } 
} 
    } 

HTML:

<!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> 
<title></title> 
<script src="http://code.jquery.com/jquery-1.4.3.min.js" type="text/javascript></script> 
<link href="main.css" rel="stylesheet" type="text/css" /> 
<script type="text/javascript"> 
     function search() { 
     if ($("#txtSearch").val() != "") { 

     $(".divResult").show(); //show div block that contains on result 
     $(".loading").show(); // show loading text while getting result 

    //call web searvice 
      $.ajax({ type: "POST", 
       url: "WebService.asmx/Search", //function that in web service 
       data: "{txtSearch:'" + $("#txtSearch").val() + "'}",// passing value of txtSearch input 
       contentType: "application/json; charset=utf-8", 
       dataType: "json", 
       success: function(response) { 
     //declaer client object and set to it returned result from web sevice function 
        var result = response.d; 
        $(".record").html(""); // clear previous result 

     //looping in 'result' array to get data and fill it inside ".record" div as html 
        $.each(result, function(index, res) { 

      //append img tag inside ".record" div 
         $('<img />', { 
          src: 'Images/' + res.img, 
          alt: res.Title 
         }).addClass("img").appendTo('.record'); 

      //append anchor tag inside ".record" div 
         $('<a></a>', { 
          href: res.href, 
          text: res.Title 
         }).addClass("txtResult").appendTo('.record'); 

         $(".record").append("<hr />"); 
        }); 
     //hide loading div when the data was got 
        $(".loading").hide(); 
       }, 
       error: function(msg) { 
        $(".record").html(msg.d); 
       } 

      }); 

     } 
     else { 
     $(".divResult").hide(); //hide div that contains result when the input text is empty 
     $(".record").html(""); //also loading text when the input text is empty 
     } 
    } 
</script> 
</head> 
<body> 
<div class="content"> 
    <input id="txtSearch" onkeyup="search()" type="text" /> 
<div class="divResult"> 
<div class="loading">Loading..</div> 
<div class="record"></div> 
</div> 
</div> 
</body> 
</html> 

CSS:

 .content 
    { 
     margin:50px auto; 
     text-align:center; 
     width:322px; 
    } 

    #txtSearch 
    { 
     border:solid 1px #cccccc; 
     width:320px; 
     color:#555555; 
     font: 18pt tahoma; 
     height: 20px; 
     font-size: 12px; 
     font-family: "lucida grande",tahoma,verdana,arial,sans-serif; 
    } 
    .divResult 
    { 
     position:absolute; 
     background-color:#F2F2FF; 
     border-style:solid; 
     border-width:1px; 
     border-color:#999999; 
     width:320px; 
     text-align:left; 
     display:none; 
    } 
    .img 
    { 
     padding-top: 2px; 
     width:30px; 
     height:30px; 
     float:left; 
    } 
    .txtResult 
    { 
     display:block; 
     width:320px; 
     height:30px; 
     color:#3c5899; 
     font-family: "lucida grande",tahoma,verdana,arial,sans-serif; 
     font-size: 14px; 
     font-weight: bold; 
     text-decoration:none; 
    } 
    .txtResult:hover { 
     background-color: #3c5899; 
     color: White; 
    } 
    .loading 
    { 
     font: 10pt tahoma; 
     text-align:center; 
    } 
    .record 
    { 
     margin:0px; 
    } 

ответ

2

Тип соединения, который вы делаете в своем SQL-запросе, не рекомендуется, и он может учитывать ваши повторяющиеся результаты. Я хотел бы предложить что-то больше, как это:

select 'Driver' as Type, UserId as Id, UserName as Name 
from DriverInfo 
where UserName like '%foo%' 

union 

select 'Team' as Type, Id, TeamName 
from Teams 
where TeamName like '%foo%' 

union 

select 'Track' as Type, TrackId, TrackName 
from Tracks 
where TrackName like '%foo%' 

Это даст вам результаты, как это:

 
Type  Id  Name 
----  --  ---- 
Driver 23  Foo 
Driver 73  Foo Jr. 
Team  27  Team Foo 
Team  64  Team Foobar 
Track  98  Bar Foo Field 

Вот как вы могли бы потреблять эти результаты:

while (dr.Read()) 
{ 

    resultList.Add(
     new searchResult { 
      Title = dr["Name"].ToString(), 
      img = dr["Type"].ToString() + ".png", 
      href = dr["UserId"].ToString() }); 
} 

Как, вы вероятно, получат такие результаты (декартовый продукт), где число результатов не будет A + B + C, а скорее A * B * C:

 
UserId UserName  Id TeamName  TrackId TrackName  ... 
------ --------  -- --------  ------- ---------  --- 
23  Foo   27 Team Foo  98  Bar Foo Field ... 
23  Foo   64 Team Foobar 98  Bar Foo Field ... 
73  Foo Jr.  27 Team Foo  98  Bar Foo Field ... 
73  Foo Jr.  64 Team Foobar 98  Bar Foo Field ... 

Также обратите внимание, что с тех пор, как используется select *, вы получите больше столбцов, чем вам нужно.

Update:

Вы сказали, что вы не были уверены в том, как добавить переменные в запросе.Вы должны использовать параметризованный запрос вместо конкатенации строк, чтобы сделать ваш код более чистым и защитить от атак SQL-инъекций:

+0

Точно как ответ phoog. Он продолжает поиск навсегда без каких-либо совпадений. – parek

+0

Вы уверены, что поиск просто не медленный или что вы не получаете ошибку во время выполнения запроса? У вас много строк? Выполнение 'like '% ...%'' обычно является очень дорогостоящей операцией без правильной индексации. Попробуйте запустить запрос непосредственно в базе данных (т. Е. С помощью SQL Management Studio, если вы используете MSSQL). – Jacob

+0

Правильно работает в студии управления. Можем ли мы открыть диалог чата, чтобы исправить это? – parek

1

Это декартово произведение запрос: SELECT * FROM [DriverInfo], [Teams], [Tracks] WHERE UserName LIKE '" + txtSearch + "%' OR TeamName LIKE '" + txtSearch + "%' OR TrackName LIKE '" + txtSearch + "%'"

(. Поиск в Интернете для cartesian product join для получения дополнительной информации)

Я полагаю, вы либо хотите, чтобы соединить таблицы или сделать объединение им. Из вашего примера, я ожидаю, что это будет союз. Это имеет преимущество, позволяя серверу db выполнять большую часть работы и уменьшая сетевой трафик.

Пример:

command.CommandText = "SELECT UserName FROM [DriverInfo]" 
    + "WHERE UserName LIKE '" + txtSearch + "%'" 
    + "UNION SELECT TeamName FROM [Teams]" 
    + "WHERE TeamName LIKE '" + txtSearch + "%'" 
    + "UNION SELECT TrackName FROM [Tracks]" 
    + "WHERE TrackName LIKE '" + txtSearch + "%'" 

Но вы действительно должны использовать параметр, а не конкатенации значения инлайн txtSearch. В противном случае вы серьезно уязвимы для атаки SQL-инъекций. (Поиск в Интернете для SQL injection attack для получения дополнительной информации.)

+0

Не могли бы вы исправить это для меня? – parek

+0

Это не сработало. Теперь поиск просто продолжает загружаться навсегда. – parek

Смежные вопросы