2012-02-03 2 views
1

우리 서버에 게시 된 ASP.NET C# 웹 응용 프로그램이 있습니다. 3 페이지로 구성되어 있으며 각 페이지에는 3 페이지 로그인과 같은 양식이 있습니다. 세 번째 페이지의 양식이 확인되면 사용자를 다른 사이트로 보냅니다. 여기에 약간의 그림은 내가 더 잘 설명 할 수있다 :버튼이 "이 페이지를 표시 할 수 없습니다."로 리디렉션되는 경우가 있습니다.

NamePage ---> DateOfBirthPage ---> IDNumberPage ---> OtherSite이 우리의 개발 테스트 및 스트레스 모두에서 좋은 일하고있다

테스트. 그러나 IDNumberPage의 "다음"버튼을 클릭 할 때마다 프로덕션 환경에 넣은 후 사용자는 "이 페이지를 표시 할 수 없습니다"라는 메시지와 함께 "연결 문제 진단"단추가 표시됩니다. 한 명의 사용자에게 이와 같은 문제가 발생하면 모든 사용자에게 동일한 문제가 발생합니다 (한 번 발생하면 아무도 완전히 인증 할 수 없음). NamePage 및 DateOfBirthPage는 항상 작동하며 충돌이 발생하면 IDNumberPage 링크가 변경되지 않아 충돌이 OtherSite로 리디렉션되지 않고 응용 프로그램의 앞쪽에서 발생하고 있음을 나타냅니다. 친숙한 HTTP 오류가 꺼져 있지만 페이지에 오류가 표시되지 않습니다. 서버에 들어가서 응용 프로그램을 다시 시작하면 다시 작동합니다.

좌절감을주는 부분은 어떻게 발생했는지/왜 보이는지를 알기 위해이 오류를 복제 할 수 없다는 것입니다. 주목할 만하다

어떤 것들은 :

  • 각 페이지는 MS SQL 서버 데이터베이스에 하나의 쿼리를 사용하는 각 페이지 4 개 세션 변수 (텍스트 상자 형태로 입력 된 것을 포함하는 유일한 작은 문자열까지 통과
  • 이전 페이지에서)
  • 마지막 "다음"버튼을 클릭하면 세션이 중단됩니다.
  • 모든 결과 집합/연결/명령은 리디렉션 전에 닫힙니다.
  • 리디렉션이 모두가 매우 모호한 경우 Response.Redirect(siteName, false)

죄송 사용하여 오버로드 된 버전을 사용할 수 있지만, 문제 자체가 우리에게서 숨어의 이상한 좋은 일을하고있다. 우리는 테스트 요청 (한꺼번에 많이, 일정 기간 동안 여러 번)과 다양한 로그인 조합/일반적으로 페이지를 무너 뜨리려는 시도로 서버를 망치로 시험해 보았습니다. 누구든지이 문제를 진단/수정/복제하려고 시도 할 것을 제안 할 수 있습니까?

편집 : IDNumberPage의에 클릭 기능 코드는 숨김이 문제를 일으키는 :

{ SqlConnection dbconn = new SqlConnection(Application["dbconn"].ToString()); 
       SqlCommand sqlValidate = dbconn.CreateCommand(); 
       dbconn.Open(); 
       sqlValidate.CommandText = "SELECT lastName, csn FROM Demographics WHERE lastName = '" + Session["lastName"].ToString() + "' " + 
        "AND dob = '" + Session["dobCheck"].ToString() + "' AND mrn = " + strMRN; 
       SqlDataReader results = sqlValidate.ExecuteReader(); 
       if (results.HasRows) 
       { 
        string csn = ""; 
        while (results.Read()) 
        { 
         if (!String.IsNullOrEmpty(results["csn"].ToString())) 
         { 
          csn = results["csn"].ToString(); 
          break; 
         } 
        } 
        string url = Application["surveyUrlString"] + "&lastname=" + Session["lastName"].ToString() + "&mrn=" + strMRN + "&dobday=" + Session["dobday"].ToString() 
           + "&dobmonth=" + Session["dobmonth"].ToString() + "&dobyear=" + Session["dobyear"].ToString() + "&csn=" + csn; 
        results.Close(); 
        dbconn.Close(); 
        Response.Redirect(url, false); 
} 
+0

코드/사이트를 보지 않고서는 뭔가 제안하기가 정말 어렵습니다. 테스트 버전에 대한 링크를 보낼 수있는 기회가 있습니까? –

+0

모든 것이 인트라넷이므로 링크 할 수 없지만 일부 코드로 편집 할 것입니다 – rownage

+0

어쩌면 sitename이 올바른 형식이 아니며 왜 false를 true로 설정하려고합니까? – Aristos

답변

5

문제는 SQL 연결을 누출 때문이다.

자원을 올바르게 처분하지 못했습니다. 시간이 지나면 풀이 넘쳐 앱이 죽는 지점에 도달 할 때까지 연결 풀에 스택이 생성됩니다. 재설정을하면 분명히 문제가 해결됩니다.

또한 은 응용 프로그램을 테스트하는 방법에 따라 "스트레스"테스트에 표시되지 않을 수 있습니다.

해결책은 데이터베이스 호출을보다 잘 처리 할 수 ​​있도록 코드를 다시 포맷하는 것입니다.

{ 
    string url = string.empty; 

    using (SqlConnection dbconn = new SqlConnection(Application["dbconn"].ToString())) { 
     using (SqlCommand sqlValidate = dbconn.CreateCommand()) { 
      dbconn.Open(); 
      sqlValidate.CommandText = "SELECT lastName, csn FROM Demographics WHERE lastName = '" + Session["lastName"].ToString() + "' " + 
       "AND dob = '" + Session["dobCheck"].ToString() + "' AND mrn = " + strMRN; 
      using (SqlDataReader results = sqlValidate.ExecuteReader()) { 
       if (results.HasRows) { 
        string csn = ""; 
        while (results.Read()) 
        { 
         if (!String.IsNullOrEmpty(results["csn"].ToString())) 
         { 
          csn = results["csn"].ToString(); 
          break; 
         } 
        } 
        url = Application["surveyUrlString"] + "&lastname=" + Session["lastName"].ToString() + "&mrn=" + strMRN + "&dobday=" + Session["dobday"].ToString() 
          + "&dobmonth=" + Session["dobmonth"].ToString() + "&dobyear=" + Session["dobyear"].ToString() + "&csn=" + csn; 
       } 
      } // sqldatareader 
     } // using sqlcommand 
    } // using sqlconnection 
    if (!String.IsNullOrEmpty(url)) { 
     Response.Redirect(url, false); 
    } 
} 

모든 것이 정리 된 후에야 리디렉션됩니다.

SqlConnection, SqlCommandSqlDataReader은 모두 IDisposable을 구현합니다. 사용 후에는 적절히 청소해야합니다. 그렇지 않으면 리소스가 걸리게됩니다. 이 작업을 수행하는 "가장 좋은"방법은 using 절로 래핑하는 것입니다. 이렇게하면 코드 블록이 다른 객체와 같이 가비지 수집되지 않기 때문에 종료되면 코드 블록이 올바르게 제거됩니다.


또한 위 코드는 부수적 인 이점이 있습니다. 즉, 오류가 발생하면 그 후에도 계속 정리됩니다. DB 서버가 응답하지 않거나 쿼리를 실행할 때 몇 가지 유형의 오류가 발생하는 경우 게시 된 원래 코드가 분명히 유출되는 반면.

dboCheck, lastname 및 mrn 매개 변수에 포함 된 값에 따라 쿼리가 오류가 발생할 수 있습니다. 예를 들어 dobCheck 필드에 "BOB"가 전달되었거나 mrn에 대해 Nothing이 전달 된 경우 ... dob가 데이터베이스의 datetime 필드 인 경우 쿼리에서 누수 된 연결을 발생시키는 오류가 발생합니다. 충분한 시간을 보내고 사이트가 다운되었습니다.

더 이상의 리뷰를 통해 나는 아마도 그 일이 일어난 것 같아요. 사람들이 쓰레기 데이터를 쏟아 부어 앱이이 시점에 도달 할 수 있고 쿼리가 실패하고 있습니다. 대부분 이것은 테스트 케이스에서 처리 한 것이 아닙니다.


사이드 참고 : 이는 연결은을 사용하여 SQL 문을 작성하지 마십시오. 그것은 완벽한 보안입니다. 최소한 쿼리를 매개 변수화하십시오.

+0

다음은 문제를 약간 더 자세히 설명하는 좋은 게시물입니다. http://www.alwaysgetbetter.com/blog/2008/02/15/sql-connections-in-aspnet-what-you-learned-is-wrong/ – NotMe

+0

쓰레기 데이터에 대해 잘 모르겠습니다. 사람들이이 애플리케이션을 사용하는 위치는 터치 스크린이며, 각 필드에 필요한 키만 표시하도록 화면 키보드를 설계했습니다. 예를 들어 날짜 필드에는 문자가 없습니다.하지만 다시 디자인했습니다. 'using' 문을 사용합니다. 오늘까지 배포 할 수 없지만 계속 게시 해 드리겠습니다. 나는 궁금해. 리다이렉트가 정말로 'using'문 밖에 있어야 할까? – rownage

+0

@koage : 리디렉션이 확실하지 않습니다. 개인적으로 두 가지 규칙이 있습니다. 첫째, 절 사용은 가능한 빨리 끝내야합니다. 둘째, 리디렉션이 항상 최후의 방법이라는 것을 코딩합니다. 당신은 확실히 두 가지 방법을 시도 할 수 있습니다. – NotMe

0

좋은 답변 Chris, 하나의 질문은 using 문에 .Close() 문이 없습니다. 연결 및 datareader 모두 :

  results.Close(); 
     } // using sqldatareader 
     } // using sqlcommand 
     dbconn.Close(); 
    } // using sqlconnection  
+0

사실, .close()가 using 문 안에 있으면 호출 할 필요가 없습니다. 코드 블록이 끝나면 dispose 메서드가 호출되어 .close() 메서드가 호출됩니다. – NotMe

+0

위대한, 감사 크리스 :) – CoderRoller