2014-05-19 4 views
1

저는 C#과 SQL을 사용하여 3 계층 응용 프로그램을 설계하는 Windows 양식을 설계하고 있습니다. 저장 프로 시저를 사용하여 데이터베이스에 연결된 사용자 등록 페이지를 설계했습니다. 사용자로부터 입력을 받아들이 기 위해 텍스트 상자를 넣었습니다. 내 사용자 이름 열에 고유 한 제약 조건을 사용했습니다. 이후 나는 BLL에 내 register_user 함수를 배치하고 UI에서 버튼에서 그것을 호출하는 3 계층 응용 아키텍처를 사용하고 있습니다. 내가 입력 한 때 사용자 이름이 텍스트 상자에 고유 한 제약 조건의 예외 (예상대로) throw됩니다 반복하지만이 메시지는 Windows 상자에 표시되어야하며 내 응용 프로그램을 작동하지 않아야합니다. register_user 함수에서 try catch를 사용하려고했지만 아무 쓸모가 없었습니다. 마찬가지로 나는 또한 내 UI (단추 등록)에서 try catch를 사용하려고했지만 다시 실패했다.3-tier 응용 프로그램의 SQL 예외 (고유 식별자)에 대한 C#의 메시지 상자에 오류 메시지가 표시됩니다.

// BLL

public void register_user(string First_Name,string Last_Name,string User_Name,string Password,string Date_Of_Birth,string Security_Question,string Security_Answer) 
    { 
     try 
     { 
      DAL obj = new DAL(); 
      obj.OpenConnection(); 
      obj.LoadSpParameters("UR", First_Name, Last_Name, User_Name, Password, Date_Of_Birth, Security_Question, Security_Answer); 
      obj.ExecuteQuery(); 
      obj.UnLoadSpParameters(); 
     } 
     catch (SqlException ex) 
     { 
      MessageBox.Show(ex.ToString()); 
     } 
     finally 
     { 
      DAL obj2 = new DAL(); 
      obj2.CloseConnection(); 
     } 
     } 

// UI

private void register_button_Click(object sender, EventArgs e) 
    { 

     if (first_name_text.Text == "" || last_name_text.Text == "" || user_name_text.Text == "" || password_text.Text == "" || confirm_password_text.Text == "" || answer_txt.Text == "") 
     { 

      alert1_label.Show(); 
      error1_label.Show(); 
      error1_label.Text = "You cannot left mandatory fields empty"; 
     } 

     if (password_text.Text.Length <= 8) 
     { 

      alert1_label.Show(); 
      error1_label.Show(); 
      error1_label.Text = "Password must be greater than 8 characters"; 
      password_text.Clear(); 
      confirm_password_text.Clear(); 
      return; 


     } 
     if (first_name_text.Text.Any(Char.IsDigit) || first_name_text.Text.Any(Char.IsPunctuation) || first_name_text.Text.Any(Char.IsSeparator) || first_name_text.Text.Any(Char.IsSymbol)) 
     { 
      alert1_label.Show(); 
      error1_label.Show(); 
      error1_label.Text = "Numbers and Special Characters are not allowed in first name"; 
      first_name_text.Clear(); 
      return; 
     } 
     if (last_name_text.Text.Any(Char.IsDigit) || last_name_text.Text.Any(Char.IsPunctuation) || last_name_text.Text.Any(Char.IsSeparator) || last_name_text.Text.Any(Char.IsSymbol)) 
     { 
      alert1_label.Show(); 
      error1_label.Show(); 
      error1_label.Text = "Numbers and Special Characters are not allowed in last name"; 
      last_name_text.Clear(); 
      return; 
     } 
     if (!user_name_text.Text.Any(Char.IsLetter)) 
     { 
      alert1_label.Show(); 
      error1_label.Show(); 
      error1_label.Text = "User Name must contain atleast one alphabet, and must be atleast 4 characters long."; 
      user_name_text.Clear(); 
      return; 
     } 
     if (user_name_text.Text.Length <= 3) 
     { 
      alert1_label.Show(); 
      error1_label.Show(); 
      error1_label.Text = "User Name must contain atleast one alphabet, and must be atleast 4 characters long."; 
      user_name_text.Clear(); 
      return; 
     } 

     else 
     { 
      try 
      { 
      error1_label.Hide(); 
      alert1_label.Hide(); 
      BLL obj = new BLL(); 
      obj.register_user(first_name_text.Text, last_name_text.Text, user_name_text.Text, password_text.Text, date_of_birth_text.Text, security_question_text.SelectedItem.ToString(), answer_txt.Text); 

       MessageBox.Show("Registration Successful"); 
       UP frm = new UP(); 
       frm.Text = "Welcome" + " " + first_name_text.Text; 
       this.Dispose(); 
       frm.Show(); 
      } 
      catch(SqlException ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 
    } 
+0

오류와 함께 실패하거나 지금 작동합니까? – scheien

+0

예외 오류로 인해 실패했지만이 오류를 메시지 상자에 표시하려고합니다. –

+0

예외는 어떤 행에서 발생합니까? – scheien

답변

1

BLL의 문제 중 하나는 열려 있지 않은 연결 닫기입니다. register_user 메서드에는 new DAL() 개체를 만드는 finally 블록이 있고 CloseConnection을 호출합니다.

구현을 보지 않고 try 블록에서 만든 DAL 개체를 닫고 싶다고 생각합니다. 그렇다면 try 블록 외부에서 obj 변수를 들어 올려 try 및 finally 블록에서 사용할 수있게 할 수 있습니다.

변수에 C#의 blockscope가 있음을 기억하십시오.

public void register_user(string First_Name,string Last_Name,string User_Name,string Password,string Date_Of_Birth,string Security_Question,string Security_Answer) 
{ 
    DAL obj = null; // initialize to a value 
    try 
    { 
     obj = new DAL(); 
     obj.OpenConnection(); 
     obj.LoadSpParameters("UR", First_Name, Last_Name, User_Name, Password, Date_Of_Birth, Security_Question, Security_Answer); 
     obj.ExecuteQuery(); 
     obj.UnLoadSpParameters(); 
    } 
    catch (SqlException ex) 
    { 
     MessageBox.Show(ex.ToString()); 
    } 
    finally 
    { 
     if (obj!=null) // check for null in case the constructor did throw an exception 
     { 
      obj = new DAL(); 
      obj.CloseConnection(); 
     } 
     else 
     { 
      Debug.Assert(obj!=null, "DAL not intialized"); 
     } 
    } 
    } 

이 답변의 범위를 벗어나는 이유와 예외를 잡을 때는 다시 방문해야합니다. 일반적으로 예외 처리 방법을 알고있는 경우에만 예외를 catch합니다. 현재 코드 예제에서 BLL과 UI 레이어는 모두 예외를 처리합니다. 제대로 수행되면 BLl 계층은 사용자에게 오류를 표시 할 책임이 없어야합니다. 호출자 (이 경우 UI 레이어)에게 오류를 전달해야하며 호출자는 수행 할 작업을 결정할 수 있습니다.

위의 샘플에서 해당 조언을 ​​취하면 MessageBox.Show을 제거해야하며 로깅 및/또는 오류 수집으로 대체해야합니다.

catch (SqlException ex) 
{ 
    MessageBox.Show(ex.ToString()); 
} 

에 :

catch (Exception ex) 
{ 
    MessageBox.Show(ex.ToString()); 
} 

는 시도 블록 내 오류, 오류뿐만 아니라 "SQLEXCEPTION"타입을 잡는다이 방법

+0

오 !! 어떻게 그렇게 바보가 될 수 있을까 .. :) 적시에 응답을 주셔서 감사합니다 :) –

0

당신처럼 특정 예외를 포착하는 것이 좋습니다 "캐치 (의 SQLException 전 감사 : 내 여기에 코드를 게시하고) ",하지만 디버깅을 위해"catch (SqlException ex) "를 다음 문과 같이 바꾸십시오.

클라이언트와 비즈니스 계층 모두에서이 작업을 수행 한 다음 중단 점을 배치하고 디버그 한 후 결과를 확인하십시오.

제 생각 엔 클라이언트에서 catch되지 않은 다른 유형의 예외를 생성하는 첫 번째 catch 문에서 뭔가가 발생합니다.

+0

디버깅을 위해 예외가 잡히지 않으면 훨씬 쉽습니다. 또 다른 가능성은 첫 번째 기회 wexception에 휴식하는 것입니다 : http://stackoverflow.com/questions/8218249/how-do-i-enable-visual-studio-2010-to-break-when-a-first-chance-exception -happen – rene

0
는 캐치를 변경

. 현재 오류는 "SqlException"이 아닌 다른 것일 수 있습니다.

+0

아니, 실제로는 확실히 SQL 예외입니다. –

+0

확실한 경우 MessageBox에 오류가 표시되지 않는 이유는 무엇입니까? 당신이 그것을 시도해야 적어도 – W0lfw00ds

+0

사실 나는 이미 당신의 제안에 노력했지만 실패했습니다. –

0

코드의 해당 지점에서 UI에 액세스 할 수 없기 때문에 오류가 발생했을 가능성이 큽니다.

데이터 계층에서 UI 구성 요소를 생성하도록 n 계층의 디자인 원칙을 위반합니다. n 계층에서는 예외를 처리하는 계층과 메시지를 전송하는 방법을 초기 설계에서 결정해야합니다.

일반적인 계획은 :

  • 모든 예외는 그들이 적절하게 처리하는 UI 층까지 부풀어있다. 데이터 또는 비즈니스 계층에서 유일한 장애는 계층 내에서 올바르게 처리되거나 catch, log 및 rethrow 할 수있는 오류 때문입니다.
  • 메시지를 비즈니스 계층에서 반환 할 수있는 사용자 지정 반환 형식이 있어야합니다. 이것은 모든 BL 메소드 및 일종의 전역 오류 저장소 ("하나 이상의 오류가 발생했습니다. 여기에는 오류 로그"유형 메시징) 또는 예외가 포함 된 결과 유형 또는 복합 결과 객체와 같은 성공한 부울 반환 일 수 있습니다. 트랜잭션 상태 등에 대한 다른 정보도있을 수 있습니다.
+0

같은 문제가 나를 혼란스럽게 만들었다. 제 2의 계획을 첫 번째 옵션으로 사용하고 있었지만, 실패 할 때 무엇을 반환해야하는지 혼란스러워했습니다. 하지만 지금은 해결되었습니다 :) –