5

Thực tiễn tốt nhất để xử lý ngoại lệ trong NHibernate là gì?Xử lý ngoại lệ NHibernate

Tôi đã có một SubjectRepository như sau:

public void Add(Subject subject) 
    { 
     using (ISession session = HibernateUtil.CurrentSession) 
     using (ITransaction transaction = session.BeginTransaction()) 
     { 

      session.Save(subject); 
      transaction.Commit(); 
     } 
    } 

Và một thử nghiệm đơn vị như sau:

 [Test] 
    public void TestSaveDuplicate() 
    { 
     var subject = new Subject 
     { 
      Code = "En", 
      Name = "English" 
     }; 

     _subjectRepository.Add(subject); 

     var duplicateSubject = new Subject 
     { 
      Code = "En", 
      Name = "English1" 
     }; 

     _subjectRepository.Add(duplicateSubject); 
    } 

tôi đến điểm xử lý các lỗi được tạo ra bởi các đơn vị kiểm tra và có một chút khó khăn. Điều này không thành công như mong đợi, mặc dù với một GenericADOException, tôi đã mong đợi một ConstraintViolationException hoặc một cái gì đó tương tự (có một ràng buộc duy nhất trên mã chủ đề ở cấp cơ sở dữ liệu).

ADOException bao bọc một ngoại lệ MySQL có thông báo lỗi hợp lý nhưng tôi không muốn bắt đầu phá vỡ đóng gói bằng cách chỉ ném ngoại lệ bên trong. Đặc biệt là MySQL không được hoàn thành như là kết thúc trở lại cho dự án này.

Lý tưởng nhất là tôi muốn có thể nắm bắt ngoại lệ và trả lại lỗi hợp lý cho người dùng tại thời điểm này. Có cách tiếp cận thực hành tốt nhất để xử lý các ngoại lệ NHibernate và báo cáo lại cho người dùng những gì đã xảy ra không và tại sao?

Cảm ơn,

Matt

Trả lời

13

tôi sẽ xử lý nó trong Add phương pháp như vậy:

public void Add(Subject subject) 
{ 
    using (ISession session = HibernateUtil.CurrentSession) 
    using (ITransaction transaction = session.BeginTransaction()) 
    { 
     try 
     { 
      session.Save(subject); 
      transaction.Commit(); 
     } 
     catch (Exception ex) 
     { 
      transaction.Rollback(); 
      // log exception 
      throw; 
     } 
    } 
} 

Trong khối catch, trước tiên bạn nên rollback giao dịch và đăng nhập các ngoại lệ. Sau đó, lựa chọn của bạn là:

  1. rethrow cùng một ngoại lệ, đó là những gì phiên bản của tôi không
  2. Wrap nó trong ngoại lệ của riêng bạn và ném rằng
  3. Swallow the ngoại lệ bởi không làm gì cả, mà là rất hiếm khi một tốt ý tưởng

Bạn không có bất kỳ tùy chọn thực nào để xử lý ngoại lệ trong phương pháp này. Giả sử rằng giao diện người dùng gọi phương thức này, nó sẽ gọi nó trong try..catch riêng của nó và xử lý nó bằng cách hiển thị một thông báo lỗi có ý nghĩa cho người dùng.Bạn có thể thực hiện kiểm tra đơn vị của mình bằng cách sử dụng thuộc tính ExpectedException (type).

Để trả lời câu hỏi của bạn trực tiếp, bạn nên tạo "lỗi hợp lý" của riêng mình bằng cách mở rộng Ngoại lệ và ném ngoại lệ đó với ngoại lệ ban đầu dưới dạng Ngoại lệ bên trong của nó. Đó là kỹ thuật gói ngoại lệ mà tôi đã liệt kê trong (2).

+0

Tôi nghĩ rằng việc bao gồm ngoại lệ cũng là tùy chọn tốt nhất. Ngoại lệ bên trong là một cái gì đó dọc theo dòng của MySQLException Message = "Mục nhập trùng lặp 'En' cho khóa 3". Vì điều này sẽ được gọi trực tiếp bởi giao diện người dùng, tôi muốn trả lại một thông điệp có ý nghĩa. –

+0

Đây có phải là ý tưởng hay, để bắt TẤT CẢ ngoại lệ và quấn nó? – VikciaR

+0

Bạn có thể loại bỏ hầu hết mã này, nếu bạn chỉ cần sửa lại ngoại lệ - nếu giao dịch không được cam kết rõ ràng, nó sẽ được cuộn lại khi phiên đóng (hoặc rõ ràng nếu lệnh gọi cam kết đang ném ngoại lệ, nó sẽ cố gắng để cuộn nó trở lại), vì vậy chỉ cần để cho các ngoại lệ đi và NH sẽ chăm sóc các giao dịch nếu nó đã không cam kết - bạn sẽ nhận được các hiệu ứng tương tự với mã sạch hơn. –

1

Các câu hỏi chung sẽ là, những gì bạn muốn nói với người sử dụng, và là người người sử dụng?

Nếu người dùng đôi khi sẽ là một máy tính khác (nghĩa là đây là dịch vụ web), thì bạn sẽ muốn sử dụng cơ chế thích hợp để trả lại lỗi SOAP hoặc lỗi HTTP.

Nếu người dùng đôi khi sẽ là giao diện người dùng của một số loại, bạn có thể muốn hiển thị thông báo cho người dùng, nhưng bạn sẽ nói gì với người dùng để có thể làm gì đó? Ví dụ, hầu hết các trang web sẽ nói, "xin lỗi, chúng tôi đã có một lỗi không mong muốn", không có vấn đề gì lý do. Đó là bởi vì thường không có gì người dùng có thể làm về lỗi.

Nhưng trong cả hai trường hợp, lựa chọn cách nói "người dùng" là vấn đề đối với lớp Trình bày (tầng giao diện người dùng), không phải cho DAL. Bạn nên có thể bọc ngoại lệ từ DAL trong một loại ngoại lệ khác, nhưng chỉ khi bạn định thay đổi tin nhắn. Bạn không cần lớp ngoại lệ của riêng bạn, trừ khi người gọi của bạn sẽ làm điều gì đó khác biệt nếu đó là một ngoại lệ truy cập dữ liệu thay vì một số loại khác.

2

Tất cả ngoại lệ Nhibernate không thể khôi phục được, bạn có thể xem lại thiết kế của lớp ứng dụng/dữ liệu nếu bạn đang cố khôi phục từ các ngoại lệ nhibernate. Bạn cũng có thể xem qua số exception translation implementaion của Spring.net Ngoài ra, bạn xử lý thủ công các giao dịch về ngoại lệ là tẻ nhạt và dễ bị lỗi, hãy xem nhibernate's contextual sessions. Spring.net cũng có một số người trợ giúp tốt đẹp xung quanh nhibernate.

+0

Liên kết phiên theo ngữ cảnh của NHibernate bị hỏng. –

+0

Liên kết phiên làm việc theo ngữ cảnh của NHibernate từ archive.org: https://web.archive.org/web/20090327153540/http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/architecture.html –

1

Tôi có thể xác thực đầu vào trước khi lưu đối tượng; theo cách đó, bạn có thể triển khai bất kỳ xác thực nào bạn thích (ví dụ: kiểm tra độ dài của Mã Chủ đề cũng như thực tế là không có bất kỳ trùng lặp nào) và trả lại các lỗi xác thực có ý nghĩa cho người dùng.

Logic như sau; các trường hợp ngoại lệ được sử dụng để cho biết các trường hợp ngoại lệ mà chương trình của bạn không đáp ứng. Người dùng nhập Mã chủ đề trùng lặp trong ví dụ của bạn ở trên là chương trình mà bạn nên cung cấp; vì vậy, thay vì xử lý một ngoại lệ vì ràng buộc DB bị vi phạm (đó là một sự kiện đặc biệt và không nên xảy ra), bạn muốn xử lý kịch bản đó trước và chỉ cố gắng lưu dữ liệu khi bạn biết dữ liệu bạn 'tiết kiệm là chính xác.

Lợi thế khi triển khai tất cả các quy tắc xác thực trong DAL của bạn là bạn có thể đảm bảo rằng dữ liệu đi vào DB của bạn là hợp lệ theo quy trình kinh doanh của bạn một cách nhất quán hơn là dựa vào các ràng buộc trong DB của bạn những người cho bạn.