5

NHibernate에서 예외를 처리하는 가장 좋은 방법은 무엇입니까? 다음과 같이NHibernate 예외 처리

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

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

을 그리고 단위 테스트 :

나는 다음과 SubjectRepository있어

 [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); 
    } 

내가 단위 테스트에 의해 생성 된 오류를 처리하는 지점에 도착했고 조금 붙어있어. 이것은 예상대로 실패하지만 GenericADOException을 사용하면 ConstraintViolationException 또는 비슷한 (데이터베이스 레벨의 주제 코드에 고유성 제한 조건이 있음)을 기대하고있었습니다.

ADOException은 합리적인 오류 메시지가있는 MySQL Exception을 래핑하지만 내부 예외를 throw하여 캡슐화를 중단하기를 원하지 않습니다. 특히 MySQL은이 프로젝트의 백 엔드로 확정되지 않았습니다.

이상적으로 나는이 시점에서 예외를 잡아 내고 사용자에게 현명한 오류를 반환 할 수 있기를 바랍니다. NHibernate Exceptions을 처리하고 무엇이 잘못되었는지와 왜 사용자에게 백업되었는지에 대한 문서화 된 모범 사례 접근 방법이 있습니까?

감사합니다,

매트

답변

13

I는 다음과 같은 추가 방법에 그것을 처리 할 것 :

catch 블록에서
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; 
     } 
    } 
} 

먼저 트랜잭션을 롤백하고 예외를 기록해야합니다. 그런 다음 옵션은 다음과 같습니다

  1. 다시 던진다 내 버전은
  2. 자신의 예외를 랩하고
  3. 매우 드물게 좋은없는, 아무것도하지 않고하여 예외를 삼켜 것을 던져 무엇이며 같은 예외 아이디어

이 방법으로 예외를 처리하기위한 실제 옵션이 없습니다. UI가이 메소드를 호출한다고 가정하면, 사용자는 자신의 try..catch에서이를 호출하고 사용자에게 의미있는 오류 메시지를 표시하여 처리해야합니다.ExpectedException (type) 속성을 사용하여 단위 테스트를 통과시킬 수 있습니다.

직접 질문에 대답하려면 Exception을 확장하여 고유 한 "현명한 오류"를 만들어서 원래 예외가있는 InnerException으로 던져야합니다. 이것은 (2)에 나열된 예외적 인 래핑 기술입니다.

+0

예외를 배치하는 것이 가장 좋은 방법이라고 생각합니다. 내부 예외는 MySQLException의 행을 따라 발생합니다. Message = "키 3의 중복 엔트리 'En'입니다. 프런트 엔드에서 직접 호출하므로 의미있는 메시지를 보내고 싶습니다. –

+0

모든 예외를 잡아서 감싸는 것이 좋은 생각입니까? – VikciaR

+0

예외를 다시 던지면이 코드의 대부분을 제거 할 수 있습니다. 트랜잭션이 명시 적으로 커밋되지 않은 경우 세션이 닫힐 때 롤백됩니다 (또는 커밋 호출이 예외를 throw하는 경우 분명히 롤백을 시도합니다.) 따라서 예외를 적용하고 NH가 커밋하지 않은 경우 NH이 트랜잭션을 처리하게합니다. 코드를 깨끗하게 만들면 동일한 효과를 얻을 수 있습니다. –

1

될 것입니다 일반적인 질문, 당신은 사용자에게 무엇을 원하는가, 사용자가 누구인가?

사용자가 때때로 다른 컴퓨터 (즉, 웹 서비스) 인 경우 적절한 메커니즘을 사용하여 SOAP 오류 또는 HTTP 오류를 반환하고자 할 것입니다.

사용자가 어떤 종류의 UI가되는 경우 사용자에게 메시지를 표시 할 수 있지만 사용자에게 무엇을 할 수 있도록 알려줄 수 있습니까? 예를 들어, 대부분의 웹 사이트는 "죄송합니다. 이유가 무엇이든간에 예기치 않은 오류가 발생했습니다."라고 말합니다. 대개 사용자가 오류에 관해 할 수있는 일이 없기 때문입니다.

두 경우 모두 "사용자"를 나타내는 방법은 DAL이 아닌 프레젠테이션 계층 (UI 계층)의 문제입니다. 다른 예외 유형의 DAL에서 예외를 래핑해야하지만 메시지를 변경해야합니다. 호출자가 다른 종류가 아닌 데이터 액세스 예외 인 경우 다른 것을 수행하지 않는 한 자체 예외 클래스는 필요하지 않습니다.

2

Nhibernate 예외는 모두 복구 할 수 없으므로 nhibernate 예외에서 복구하려는 경우 app/data 계층의 디자인을 다시 검토 할 수 있습니다. spring.net의 exception translation implementaion 도 예외 처리 트랜잭션을 수동으로 처리하는 것은 지루하고 오류가 발생하기 쉽습니다. nhibernate's contextual sessions을 살펴보십시오. Spring.net에는 nhibernate에 대한 멋진 도우미가 있습니다.

+0

NHibernate의 콘텍스트 세션의 링크가 끊어졌습니다. –

+0

archive.org에서 NHibernate의 문맥 세션의 링크 작업 : https://web.archive.org/web/20090327153540/http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/architecture.html –

1

개체를 저장하기 전에 입력 내용의 유효성을 검사 할 수 있습니다. 그렇게하면 원하는 유효성 검사 (예 : 제목 코드의 길이 및 중복이 없다는 사실 확인)를 구현하고 의미있는 유효성 검사 오류를 다시 사용자에게 전달할 수 있습니다.

로직은 다음과 같습니다. 예외는 프로그램이 처리하지 않는 예외적 인 상황을 나타내는 데 사용됩니다. 위의 예에서 중복 된 주체 코드를 입력하는 사용자는 프로그램이 제공해야하는 항목입니다. 따라서 DB 제약 조건이 위반 (예외적 인 이벤트이므로 발생하지 않아야 함)하기 때문에 예외를 처리하는 것이 아니라 먼저 해당 시나리오를 처리하고 데이터를 저장하려고 시도하는 것이 좋습니다. 다시 저장하는 것이 맞습니다.

귀하의 DAL에 모든 유효성 검사 규칙을 구현할 때의 이점은 DB에 들어가는 데이터가 DB의 제약 조건에 의존하지 않고 일관된 방식으로 비즈니스 프로세스에 따라 유효하다는 것입니다 당신을위한 것들.