2013-02-21 25 views
5

Tôi có ứng dụng web dựa trên 3 tầng. Tôi muốn sử dụng Tôi đang sử dụng thử catch khối trong lớp logic kinh doanh của tôi. Có phải sử dụng khối try/catch trong logic nghiệp vụ hay tôi cần sử dụng nó trong lớp giao diện người dùng của tôi?nơi đặt thử/bắt trong kiến ​​trúc 3 tầng

xem mã của tôi cho DAL.

Data Access Layer 

#region Insert in to Logbook 
public int Insert_LogBook(string Vehicle_Number, DateTime Vehicle_Booking_Date, TimeSpan Time_From, TimeSpan Time_To, int KM_Start, int KM_End, string Vehicle_Used_By, string Cost_Code, string Budget_Line, DateTime Entry_Date) 
{ 
    try 
    { 
     SqlCommand com = new SqlCommand("Insert_LogBook", con); 
     com.Parameters.Add("@Vehicle_Number", SqlDbType.NVarChar, 100).Value = Vehicle_Number; 
     com.Parameters.Add("@Vehicle_Booking_Date", SqlDbType.DateTime).Value = Vehicle_Booking_Date; 
     com.Parameters.Add("@Time_From", SqlDbType.Time).Value = Time_From; 
     com.Parameters.Add("@Time_To", SqlDbType.Time).Value = Time_To; 
     com.Parameters.Add("@KM_Start", SqlDbType.Int).Value = KM_Start; 
     com.Parameters.Add("@KM_End", SqlDbType.Int).Value = KM_End; 
     com.Parameters.Add("@Vehicle_Used_Byr", SqlDbType.VarChar, 100).Value = Vehicle_Used_By; 
     com.Parameters.Add("@Cost_Code", SqlDbType.NVarChar, 50).Value = Cost_Code; 
     com.Parameters.Add("@Budget_Line", SqlDbType.NVarChar, 50).Value = Budget_Line; 
     com.Parameters.Add("@Entry_Date", SqlDbType.DateTime).Value = Entry_Date; 
     con.Open(); 
     int res = com.ExecuteNonQuery(); 

    } 
    catch (Exception ex) 
    { 
     WebMsgBox.Show(ex.Message); 
    } 
    finally 
    { 
     con.Close(); 
     con.Dispose(); 

    } 
    return 1; 
} 
#endregion 

Vì vậy, tôi nên sử dụng nó trong bal hoặc trong lớp giao diện người dùng hoặc mã của tôi là ok. bởi vì nếu tôi không sử dụng try/catch trong lớp UI của tôi, nó sẽ không bắt ngoại lệ (nếu có) và hiển thị trang lỗi.

Trả lời

3

Xử lý và ném ngoại lệ là thứ mà tôi thấy hầu hết các nhà phát triển mà tôi từng làm việc đều hiểu.

  • Ngoại lệ cho phép bạn tìm lỗi trong mã của mình.
  • Họ tạm dừng chương trình đang chạy để ngăn chặn 'thương tích' đối với doanh nghiệp.
  • Chúng cho phép bạn lọc giữa các ngoại lệ được mong đợi hợp lý (mạng không khả dụng trên ứng dụng dành cho thiết bị di động) so với các ngoại lệ lỗi không mong muốn như NullReferenceException.
  • Họ hiểu rõ lý do tại sao lỗi xảy ra.
  • Chúng cho phép mỗi thành phần thêm một lớp thông tin về ngữ cảnh và trạng thái để giúp gỡ lỗi, đây là kiểu bắt, quấn và ném.

Bạn có thể và nên sử dụng try/catch/(cuối cùng) khá nhiều bất cứ nơi nào, nhưng ...

Bạn sử dụng catch chỉ khi bạn biết rằng những ngoại lệ (s) có nhiều khả năng xảy ra và có thể phục hồi từ chúng. Bạn hiếm khi nên bắt được loại ngoại lệ cơ bản. Cho phép tất cả các lỗi khác phát sinh và được tìm thấy bởi người lập trình/người kiểm tra/người dùng.

Bạn có thể muốn bắt loại ngoại lệ cơ sở nếu bạn định ném một ngoại lệ khác và đính kèm ngoại lệ ban đầu là InnerException.

Bạn không nên nghĩ hai lần hoặc lười biếng về việc tạo các loại ngoại lệ của riêng mình. Ví dụ, bạn có thể muốn viết một DataAccessException và ném rằng với các ngoại lệ bị bắt trong tầng được đính kèm trong InnerException. Bằng cách này, việc ghi nhật ký của bạn sẽ ghi lại một loại ngoại lệ cho thấy chính xác hơn nơi xảy ra lỗi và mã gọi có thể chọn chỉ để bắt DataAccessException và thực hiện thử lại hoặc một cái gì đó.

Bạn cũng có thể xem xét làm cho trừu tượng DataAccessException và phân lớp các ngoại lệ cụ thể hơn như SqlDataAccessException hoặc SecurityDataAccessException.

Như bạn đã biết, cuối cùng bạn sử dụng khi bạn muốn đảm bảo một số mã được chạy trong trường hợp có lỗi, ngay cả khi bạn không nắm bắt và xử lý ngoại lệ. Trong các tình huống mà bạn phải luôn phát hành tài nguyên, thử/cuối cùng sẽ trở thành một mẫu chuẩn.

Ngoài ra, khi có thể, hãy thử/nắm bắt xung quanh bản vá mã cụ thể nhất mà bạn có thể xử lý lỗi, cho phép các lỗi mã hóa trong mã xung quanh làm hỏng ứng dụng.

Bạn có thể nghĩ, "Làm thế nào tôi có thể bắt một ngoại lệ cụ thể nếu tôi chưa biết ngoại lệ nào sẽ được ném?" Bạn sẽ thấy chúng được ghi lại trên phương thức ExecuteNonSql và đây là lý do tại sao nó rất quan trọng để ghi lại API/thành phần của riêng bạn với các ngoại lệ mà nó ném ra. Sử dụng các chú thích XML để làm điều này và nếu vận chuyển một DLL công khai, hãy bật trình tạo tệp nhận xét XML.

Điều này có vẻ như rất nhiều để tham gia, nhưng nó không thực tế. Khi bạn đầu tư vào việc ghi nhật ký và xử lý ngoại lệ phù hợp, bạn sẽ có thể giải quyết các lỗi trong vài phút, bạn sẽ cảm thấy giống như nhà vô địch và bạn sẽ sớm tìm hiểu để làm phiền mã nghèo của mọi người khác :)

giai đoạn này trong cuộc sống lập trình của bạn, tôi khuyên bạn nên đọc Hướng dẫn thiết kế khung bởi Cwalina và Abrams.Nó sẽ giúp bạn thực hiện các lựa chọn đúng một cách nhanh chóng về tất cả các loại câu hỏi này và bạn sẽ tìm thấy bằng cách sử dụng mã của riêng bạn là vui như sử dụng các API của Microsoft (chủ yếu).

Luke

Thêm một chút về thư. Tôi sử dụng loại điều này trong thông báo lỗi.

"Không thể {thực hiện một số chức năng}. Đã xảy ra {loại ngoại lệ}. {Cung cấp lời khuyên khắc phục hoặc lý do phổ biến cho lỗi}. Vui lòng xem {inner exception | more log entries}."

Ví dụ, trong một thành phần cho nhà nước tiết kiệm tự động trong một ứng dụng:

... 
catch(FileNotFoundException fnfe) 
{ 
    string m = String.Format("Cannot save changes. A FileNotFoundException occurred. Check the path '{0}' is valid, that your network is up, and any removable media is available. Please see inner exception.", path); 

    _log.Error(m, fnfe); 

    throw new StorageLifecycleException(m, fnfe); 
} 
0

Bạn nên đặt truy cập dữ liệu và logic nghiệp vụ của mình vào thư viện lớp học. Bạn không nên gọi các thành phần giao diện người dùng từ BLL hoặc DAL. Tạo đăng nhập vào nhật ký BLL và DAL của bạn bằng cách sử dụng một cái gì đó như log4net đặt dữ liệu lỗi ở đây.

sau đó ném ngoại lệ lên trên nếu bạn muốn thông báo cho người dùng về trạng thái lỗi.

2

Bạn nên viết một khối try-catch, nơi bạn có thể xử lý ngoại lệ. Không có thứ gì như 'luôn đặt thử ở đây hay ở đó'. Tôi thấy bạn xử lý các ngoại lệ như thế này:

catch (Exception ex) 
{ 
    WebMsgBox.Show(ex.Message); 
} 

này là xấu vì nhiều lý do:

  1. Bạn bắt generic Exception loại. Tôi đã thấy một câu hỏi về điều này vài ngày trước: https://stackoverflow.com/a/14727026/238682
  2. Bạn cố gắng xử lý ngoại lệ với WebMsgBox.Show trong Lớp Truy cập Dữ liệu của bạn, phá vỡ ranh giới của lớp đó.

Một vấn đề khác với ví dụ này là một vấn đề nhỏ nhưng tôi nghĩ điều quan trọng là về lâu dài (thiết kế mã tổng thể). Bạn nên tách logic xử lý lỗi khỏi logic ứng dụng thực tế. Vì vậy, khi bạn sử dụng khối try-catch cố gắng giảm thiểu logic bên trong, do đó, mã của bạn trở nên dễ đọc hơn.

public int Insert_LogBook(string Vehicle_Number, DateTime Vehicle_Booking_Date, TimeSpan Time_From, TimeSpan Time_To, int KM_Start, int KM_End, string Vehicle_Used_By, string Cost_Code, string Budget_Line, DateTime Entry_Date) 
{ 
    using(SqlCommand com = new SqlCommand("Insert_LogBook", con)) 
    { 
     com.Parameters.Add("@Vehicle_Number", SqlDbType.NVarChar, 100).Value = Vehicle_Number; 
     com.Parameters.Add("@Vehicle_Booking_Date", SqlDbType.DateTime).Value = Vehicle_Booking_Date; 
     com.Parameters.Add("@Time_From", SqlDbType.Time).Value = Time_From; 
     com.Parameters.Add("@Time_To", SqlDbType.Time).Value = Time_To; 
     com.Parameters.Add("@KM_Start", SqlDbType.Int).Value = KM_Start; 
     com.Parameters.Add("@KM_End", SqlDbType.Int).Value = KM_End; 
     com.Parameters.Add("@Vehicle_Used_Byr", SqlDbType.VarChar, 100).Value = Vehicle_Used_By; 
     com.Parameters.Add("@Cost_Code", SqlDbType.NVarChar, 50).Value = Cost_Code; 
     com.Parameters.Add("@Budget_Line", SqlDbType.NVarChar, 50).Value = Budget_Line; 
     com.Parameters.Add("@Entry_Date", SqlDbType.DateTime).Value = Entry_Date; 
     con.Open(); 
     int res = com.ExecuteNonQuery(); 

     return 1; 
    } 

} 

public void SomeMethodWhichUsesThatInsert() 
{ 
    try 
    { 
     //call Insert_LogBook 
    } 
    catch(SomeException e) 
    { 
     //handle 
    } 

} 
4

Nó chỉ phụ thuộc, bạn có thể sử dụng try catch khối trong cả lớp.

Nhưng vấn đề không phải là nơi bạn đang sử dụng mã xử lý ngoại lệ; vấn đề là cách bạn đang sử dụng. Trong ví dụ bạn đã cung cấp, bạn đang bắt một số chung là exception, bạn không biết đó là SqlException hay bất kỳ ngoại lệ nào khác.

Nói chung,

  1. bắt chỉ là trường hợp ngoại lệ, bạn có thể xử lý (trong ví dụ bắt SqlException, không phải tất cả các trường hợp ngoại lệ)

  2. hiển thị một thông điệp thân thiện với người sử dụng (trong ví dụ của bạn chỉ hiển thị số thông báo lỗi làm cho không có ý nghĩa đối với người sử dụng)

  3. log trừ

  4. xử lý ngoại lệ khi nó xảy ra; nếu nó là một ngoại lệ liên quan đến DAL, hãy xử lý nó trong lớp DAL, nếu nó là một ngoại lệ liên quan đến giao diện người dùng, hãy xử lý nó trong lớp UI.

+0

như vậy có thể xin hãy giải thích cách sử dụng mã của tôi? Tôi không sử dụng trong 3 tầng – Gaurav

+0

+1 Trên thông báo lỗi. Tất cả chúng ta đều lớn lên với những thông điệp vô cùng quan trọng, vì vậy chúng tôi nghĩ rằng những thông điệp đó phải có vẻ rất tệ hại. Không. Chúng có vẻ giống như một người bạn giải thích một vấn đề bằng các thuật ngữ đơn giản, thậm chí cung cấp các độ phân giải có thể. –

Các vấn đề liên quan