2009-10-21 10 views
2

이것은 나쁜 생각입니까? 동일한 효과를 얻을 수있는 더 좋은 방법이 있습니까?중첩 된 Try..catch 블록을 사용하는 것이 좋지 않습니까?

// assume that "name" is a string passed as a parameter to this code block 
try 
{ 
    MainsDataContext dx = new MainsDataContext(); 
    try 
    { 
     Main m = dx.Main.Single(s => s.Name == name); 
     return m.ID; 
    } 
    catch (InvalidOperationException) 
    { 
     Guid g = Guid.NewGuid(); 

     Main s = new Main 
     { 
      Name = name, 
      ID = g 
     }; 

     dx.Mains.InsertOnSubmit(s); 
     dx.SubmitChanges(); 

     return g; 
    } 
} 
catch (Exception ex) 
{ 
    // handle this 
} 

여기서 목표는 레코드의 ID를 얻는 것입니다. 그렇지 않으면 레코드를 생성하고 ID를 반환합니다.

답변

6

레코드가 존재하지 않으면 null 인 클래스의 기본값을 반환하는 SingleOrDefault를 사용해야합니다. 유형 Main이 클래스가 또는 경우의 DataContext

using (MainsDataContext dx = new MainsDataContext()) 
{ 
     Main m = dx.Main.SingleOrDefault(s => s.Name == name); 

     if (m == null) 
     { 
      Guid g = Guid.NewGuid(); 

      m = new Main 
      { 
       Name = name, 
       ID = g 
      }; 

     dx.Mains.InsertOnSubmit(m); 
     dx.SubmitChanges(); 

     } 

     return m.ID; 
} 
그것은 질문에서 명확하지 않다
+0

dx.Dispose()는 무엇입니까? GC에 의해 자동으로 처리되면 안됩니까? LinqToSql을 사용하여 모든 try..catches의'finally' 섹션에 이것을 넣어야합니까? – Nate

+0

@Nate, DataContext를 사용할 때 사용 문 **에서 (DataContext dx = new .......) **를 사용하는 것이 좋습니다. ** 이렇게하면 연결이 즉시 닫힙니다. 가능한 개체 및 처리됩니다. 우리가 여기서 try-catch를 사용하고 있기 때문에 우리가 연결을 처리하는 것에 상관없이 그것을 확실히 할 필요가 있습니다. 예외 여부. –

+0

그러면 연결이 빨리 닫힙니다. GC가 결국 자체적으로 종료할까요? 이제 네가 지적 했으니, 네가 그것을 만들어 낸다. 나는 단지 그것이 필요한지, 아니면 좋은 생각인지 이해하지 못한다. – Nate

6
Main m = dx.Main.SingleOrDefault(s => s.Name == name); 

if (m == default(Main)) 
{ 
    // it does not exist 
} 
else 
{ 
    // it does exist 
} 

를 사용하는 경우

MainsDataContext dx = null;  
try 
    { 
     dx = new MainsDataContext(); 

     Main m = dx.Main.SingleOrDefault(s => s.Name == name); 

     if (m == null) 
     { 
      Guid g = Guid.NewGuid(); 

      m = new Main 
      { 
       Name = name, 
       ID = g 
      }; 

     dx.Mains.InsertOnSubmit(m); 
     dx.SubmitChanges(); 

     } 

     return m.ID; 
    } 
    catch (Exception ex) 
    { 
     // handle this 
    } 
    finally 
    { 
     if(dx != null) 
      dx.Dispose(); 
    } 

IT는 키워드를 사용하여 사용하는 것이 좋습니다 struct (편집 : 방금 실제로 클래스가 있어야한다는 것을 깨달 았기 때문에) null 대신에 default()을 사용했습니다.

+0

이것은 특정 사례에 대한 답변입니다. ~'SingleOrDefault()'를 사용할 수 없을 때 중첩 된 try..catch 블록을 사용하는 일반적인 아이디어는 무엇입니까? 그게 나쁜 생각이야? – Nate

+1

@Nate Bross : 예외적 인 경우는 예외입니다. 던지기 및 예외 잡기는 매우 비싼 작업이며 코드를 매우 읽기 좋게 만들어주지는 않습니다. 정상적인 제어 흐름 (예 : 이와 같은)을 피하고 프로그램에서 예외적 인 상황이 발생할 때만 사용하십시오. –

+0

@DrJokepu : 링을 SQL로 삽입/업데이트/삭제할 때 예외를 사용해야합니까? 아니면 다른 곳에서 처리해야합니까? – keyboardP

0

아니요.하지만 내부 블록을 외부 방법으로 리파리 할 수 ​​있습니다. 당신은 순서가 두 개 이상의 요소를 포함하거나 비어 있기 때문에 싱글() InvalidOperationException이 던진 것을 알고

// handle this 

을 첫 번째 catch 블록으로 :

+3

Reffactor가 아닌 Refactor : P –

1

내 질문은 여기에 넣어하려는 어떤 코드가 될 것입니다 .

둘째, 모든 종류의 오류가 발생할 수 있습니다. 널 참조, 데이터 액세스 등 어떻게 처리 할 것인가?

처리 방법을 알고있는 것을 잡아 내고 가능하면 예외 유형으로 한정하십시오.

+0

Catch (Exception ex)는 기본적으로 일부 로깅을 수행 한 다음, throw 계층에서 처리 할 예외를 제외하는 safty net, 약식 코드 단편입니다. – Nate

+0

@ 네이트 - 완벽하게 받아 들일 만하다. 로깅 + 재실행은 기본 클래스 예외를 잡는 것이 좋은 생각 인 몇 가지 경우 중 하나입니다. – TrueWill

0

어쨌든 중첩 된 Try Catch 블록은 형제처럼 Catch 블록이 각각 다른 문제를 포착하는 것처럼 좋습니다. 오류에 대해 구체적으로 설명하는 것이 좋습니다. 캐치 올은 생산을위한 안전망이어야합니다.

관련 문제