2009-07-29 2 views
1

코드에서 버그를 발견했으며 처음에는 어떻게 발생했는지에 대해 당황 스러웠습니다.asp.net/sql 서버 무슨 일이 일어나고 있는지 파악해보십시오.

내 질문에, 일부 레코드가 삽입되지 않았 음을 나타내는 데이터베이스 ID 필드 (증가 된 ID 필드)에서 건너 뛰기를 발견했습니다. 즉, SQL SQL sprocs (아마도)가 오류를 던졌습니다. 그곳에서부터 생각해 보면, 내 비즈니스 객체가 오류를 잡아서 던져 버려야하고 즉시 종료되고 페이지의 코드 숨김으로 돌아 가야한다는 것을 의미합니다 (대신 두 번째 저장 프로 시저로 계속 진행됨). 나는 왜 이것이 가능한지 이해하지 못한다. 내 시도를 건너 뛰는 코드 실행과 관련하여 어떤 일이 벌어지고 있습니까? 뒤에

페이지 코드 :

protected void submitbutton_click(object sender, EventArgs e){ 
     try{ 
     mybusinessobject.savetodatabase() 
     } catch(Exception ex) { 
     Response.Redirect("Error.aspx"); 
     } 
} 

비즈니스 오브젝트 코드 :

public static void savetodatabase(){ 
     int ID1=-1; 
     int ID2=-1; 
     //store the billing contact 
     SqlCommand cmd1 = new SqlCommand("SaveInfo1", con); 
     cmd1.CommandType = CommandType.StoredProcedure; 
     //... 
     cmd1.Parameters.Add("@Ret", SqlDbType.Int); 
     cmd1.Parameters["@Ret"].Direction = ParameterDirection.ReturnValue; 

     try 
     { 
      con.Open(); 
      cmd1 .ExecuteNonQuery(); 
      ID1 = Convert.ToInt32(cmd1.Parameters["@Ret"].Value); 
     } 
     catch (Exception ex) { throw ex; } 
     finally { con.Close(); } 

     if (ID1 > 0) 
     { 
      SqlCommand cmd = new SqlCommand("SaveInfo2", con); 
      cmd.CommandType = CommandType.StoredProcedure; 
      //... 
      try 
      { 
       con.Open(); 
       cmd.ExecuteNonQuery(); 
       ID2= Convert.ToInt32(cmd.Parameters["@Ret"].Value); 
      } 
      catch (Exception ex) { throw ex; } 
      finally { con.Close(); } 
     } 
} 

SQL 코드 :

PROCEDURE [dbo].[SaveInfo1] 
( 
-- ... parameters ... 
) 
AS 
    INSERT INTO Table1 (...) Values (...) 
RETURN SCOPE_IDENTITY 

PROCEDURE [dbo].[SaveInfo2] 
( 
-- ... parameters ... 
) 
AS 
    DECLARE @SpecialID INT 
    INSERT INTO Table2 (...) Values (...) 
    SET @SpecialID = SCOPE_IDENTITY() 
    INSERT INTO Table3 ([ID], ...) Values (@SpecialID, ...) 
RETURN SCOPE_IDENTITY() 
+0

나는 asp.net을 사용하지 않으므로 여기서 보트를 놓칠 수 있습니다. 그것은 당신이 요구하는 문제를 일으키지 않을 것이지만 두 개의 저장 프로 시저 호출에 대한 트랜잭션이 있습니까? –

+0

아니요, 이는 문제의 일부입니다. 그러나 그것은 아직도 내가 시도 잡기를 건너 뛰는 이유를 설명하지 못한다. –

+0

내 대답보기. 나는 내가 옳다고 확신한다. 몇 주 동안 같은 문제를 해결하기 전에 내 뇌를 때리고 있었어요 – abatishchev

답변

2

귀하의 예외 처리 끔찍한입니다. 이 작업을 수행하지 마십시오 : 모든 것을 수행

catch (Exception ex) { throw ex; } 

는 예외 스택 추적을 망치는 것입니다. 그것은 throw의 시점에서 발생한 예외처럼 보입니다.

이 작업을 수행하지 마십시오 :

try{ 
    mybusinessobject.savetodatabase() 
    } catch(Exception ex) { 
    Response.Redirect("Error.aspx"); 
    } 

당신은 무슨 일이 있었는지 예외 모른다. 리디렉션이 안전한지 여부는 알 수 없으며 그 위에 모두 을 모두 잃게됩니다. 예외에 대한 정보!

또한 using 블록을 구현하는 습관을해야합니다

public static void savetodatabase() 
{ 
    using (SqlConnection con = new SqlConnection("Connectionstring")) 
    { 
     int ID1; 
     //store the billing contact 
     using (SqlCommand cmd1 = new SqlCommand("SaveInfo1", con)) 
     { 
      cmd1.CommandType = CommandType.StoredProcedure; 
      //... 
      cmd1.Parameters.Add("@Ret", SqlDbType.Int); 
      cmd1.Parameters["@Ret"].Direction = ParameterDirection.ReturnValue; 

      con.Open(); 
      cmd1.ExecuteNonQuery(); 
      ID1 = Convert.ToInt32(cmd1.Parameters["@Ret"].Value); 
     } 

     if (ID1 <= 0) 
     { 
      return; 
     } 

     int ID2 = -1; 
     using (SqlCommand cmd = new SqlCommand("SaveInfo2", con)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      //... 
      con.Open(); 
      cmd.ExecuteNonQuery(); 
      ID2 = Convert.ToInt32(cmd.Parameters["@Ret"].Value); 
     } 
    } 
} 

using 블록은 자원이 예외가 발생하는지 여부, 그 Dispose 메서드가 호출있을 것이라는 점을 보장합니다.

0

는 모 아닌가요 누군가 테이블에서 일부 레코드를 삭제 한 것 같은 시나리오입니까?

+1

첫 proc에서 RETURN SCOPE_IDENTITY를 반환하고 RETURN SCOPE_IDENTITY()를 반환하지 않아도됩니까? – MyItchyChin

0

레코드가 삭제되면 나중에 새 레코드를 삽입하더라도 해당 레코드의 고유 식별자가 재활용되지 않습니다. 원하는 경우 SQL에서 RESEED를 사용하여 ID 시드를 0으로 재설정 할 수 있지만 테이블을 지우지 않는 한 이에 대해 제안합니다. 그렇지 않으면 기본 키 위반이 발생할 수 있습니다.

또한 열의 ID 시드가 한 번에 하나씩 증가하도록 설정되어 있는지 확인하십시오.

0

코드는 단지의 Web.config에 가서 적절한 노드와 재생, 중요하지 않습니다

<customErrors mode="On|Off" /> 

P.S. finally 절의 수동 대신 연결을 자동 닫으려면 using 절을 사용하고 catch를 테스트 할 수 있습니다.

+0

이것은 예외가'catch' 블록에 의해 캐치되어 있는지 아닌지에 영향을주지 않습니다 (항상 캐치됩니다). –

+0

아니요, 그들은 그렇지 않습니다! customErrors에 대한 각각의 가능한 값을 테스트 해 보면 알 수 있습니다. VS2008TS/SQL2008/Win7RC에서도 같은 문제가 발생합니다. 눈이 아니라면 나! – abatishchev

0

단지 절차를 변경 :

PROCEDURE [dbo].[SaveInfo1] 
( 
-- ... parameters ... 
) 
AS 
    INSERT INTO Table1 (...) Values (..., some_out_of_range_value_here, ....) 
RETURN SCOPE_IDENTITY() 

일부 하드 범위 값 (그래서 삽입 실패)에서 코딩이, 다음 응용 프로그램을 실행 ...

관련 문제