2011-12-23 6 views
0

현재 자동 완성 검색 양식을 사용하는 웹 응용 프로그램을 개발 중이며 결과가 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 쿼리에서 수행하는 조인 유형은 권장되지 않으며 중복 결과를 설명 할 수 있습니다. 당신을있는 그대로

while (dr.Read()) 
{ 

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

:이 이렇게 당신에게 결과를 줄 것이다

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 

당신이 결과를 소모 할 수있는 방법이 같은 뭔가 더 좋을 것 아마도 이러한 결과 (예 : 데카르트 제품)는 결과가 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 *이 사용 중이므로 필요한 것보다 많은 열을 얻게됩니다.

업데이트 :

당신은 쿼리에 변수를 추가하는 방법에 확실하지 않았다 말했다.문자열 연결 대신 매개 변수화 된 쿼리를 사용하여 코드를보다 명확하게 작성하고 SQL 주입 공격으로부터 보호해야합니다.

cmd.CommandText = "... where UserName like @SearchPattern ... where TeamName like @SearchPattern ..."; 
cmd.Parameters.Add("@SearchPattern", txtSearch + "%"); 
+0

정확히 포그의 대답입니다. 일치 항목없이 영원히 계속 검색합니다. – parek

+0

검색어가 느리거나 검색어를 실행하는 동안 오류가 발생하지 않았습니까? 행이 많습니까? '% '%' '와 (과) 같이하는 것은 일반적으로 적절한 색인을 생성하지 않으면 매우 비싼 작업입니다. 데이터베이스에서 직접 쿼리를 실행 해보십시오 (예 : MSSQL을 사용하는 경우 SQL Management Studio 사용). – 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 서버가 더 많은 작업을 수행 할 수 있다는 장점이 있으며 네트워크 트래픽을 감소시킵니다.

예 : 당신이 정말로 txtSearch 값 인라인을 연결보다는 매개 변수를 사용해야합니다

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 + "%'" 

하지만. 그렇지 않으면 SQL 인젝션 공격에 심각하게 취약합니다. (웹에서 SQL injection attack에 대한 자세한 내용을 검색하십시오.)

+0

제발 저를 위해 교정 해 주시겠습니까? – parek

+0

그건 작동하지 않았다. 이제 검색은 영원히 로딩을 유지합니다. – parek