2017-10-02 15 views
0

다소 오래된 앱의 긴 데이터 액세스 코드를 살펴 보겠습니다. 모든 함수는 저장 프로 시저를 호출하여 Oracle DB에서 무언가를 선택합니다. 모든 아래 코드처럼 더 많거나 적은 모습을 기능 :Oracle.DataAccess.Client와 함께 사용하는 모범 사례는 무엇입니까?

public List<SomeObject> GetMeSomethingFromDB(string myParam, int anotherParam) 
{ 
    OracleConnection conn = null; 
    OracleDataReader dataReader = null; 
    try 
    { 
     conn = new OracleConnection(Settings.ConnectionString); 
     conn.Open(); 

     var cmd = new OracleCommand("STORED_PROC_NAME", conn); 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.Add(new OracleParameter("IN_MY_PARAM", OracleDbType.Varchar2)).Value = myParam; 
     cmd.Parameters.Add(new OracleParameter("IN_ANOTHER_PARAM", OracleDbType.Int32)).Value = anotherParam; 
     cmd.Parameters.Add(new OracleParameter("OUT_REF_CURSOR", OracleDbType.RefCursor)).Direction = ParameterDirection.Output; 
     dataReader = cmd.ExecuteReader(); 

     List<SomeObject> result = new List<SomeObject>(); 
     if (dataReader == null || !dataReader.HasRows) return result; 

     while (dataReader.Read()) 
     { 
      SomeObject someObject = new SomeObject 
      { 
       SomeId = (int)dataReader["SOME_ID"], 
       SomeStringValue = dataReader["SOME_STRING_VALUE"].ToString() 
      }; 

      result.Add(someObject); 
     } 

     return result; 
    } 
    catch (Exception e) 
    { 
     throw e; 
    } 
    finally 
    { 
     if (dataReader != null) 
     { 
      dataReader.Close(); 
      dataReader.Dispose(); 
     } 
     if (conn != null) 
     { 
      if (conn.State == ConnectionState.Open) conn.Close(); 
      conn.Dispose(); 
     } 
    } 
} 

내 질문은 :

  1. 일부 기능 대신 클래스 수준의 OracleConnection 변수를 사용합니다. 무엇이 선호됩니까? - 함수 수준 또는 클래스 수준 변수?
  2. dataReader == null 체크가 필요합니까? cmd.ExecuteReader() 호출 후 NULL이 될 수 있습니까?
  3. 연결과 관련하여 기능이 다릅니다. 닫기/폐기 및 판독기 닫기/폐기. 닫히거나 처분 할 올바른 방법/순서는 무엇입니까? 연결이 끊어지면 독자가 자동으로 닫기/삭제하지 않겠습니까?
  4. 가까운 미래에 Oracle.ManagedDataAccess.Client를이 프로젝트에 연결하려고합니다. 이 코드의 내용이 관리되는 데이터 액세스 클라이언트에서 작동하도록 변경됩니까?
  5. 다른 모든 유용한 정보/제안 사항은 환영합니다.

감사합니다.

+2

잡힌 예외를 다시 던지려면 'throw e;'하지 마십시오. 그냥'throw;'를 써서 스택 트레이스를 보존한다. – mason

+0

@mason - 고맙습니다. – Dimskiy

답변

3

using statement은 코드를 단순화합니다.

public List<SomeObject> GetMeSomethingFromDB(string myParam, int anotherParam) 
{ 
    using (OracleConnection conn = new OracleConnection(Settings.ConnectionString)) 
    using (OracleCommand cmd = new OracleCommand("STORED_PROC_NAME", conn)) 
    { 
     conn.Open(); 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.Add(new OracleParameter("IN_MY_PARAM", OracleDbType.Varchar2)).Value = myParam; 
     cmd.Parameters.Add(new OracleParameter("IN_ANOTHER_PARAM", OracleDbType.Int32)).Value = anotherParam; 
     cmd.Parameters.Add(new OracleParameter("OUT_REF_CURSOR", OracleDbType.RefCursor)).Direction = ParameterDirection.Output; 
     using (OracleDataReader dataReader = cmd.ExecuteReader()) 
     { 
      while (dataReader.Read()) 
      { 
       SomeObject someObject = new SomeObject 
       { 
        SomeId = (int)dataReader["SOME_ID"], 
        SomeStringValue = dataReader["SOME_STRING_VALUE"].ToString() 
       }; 
       result.Add(someObject); 
      } 
     } 
    } 
    return result; 
} 
  1. 사용 항상 로컬 연결 객체와 객체의 정확한 폐쇄 처분을 가지고 문을 사용합니다 ( 같은이 OracleDataReader 및 OracleCommand를 위해도 마찬가지)는에 포함. 이렇게하면 코드와 연결을 유지하는 데 필요한 스레드와 스레드가 ADO.NET 공급자에 의해 활성화 된 connection pooling에 의해 보장됩니다.
  2. 아니요, 호출은 필요하지 않으며 HasRows의 호출도 if 결과를 반복 할 계획입니다. 판독기가 행이 없거나 데이터 세트의 끝에 도달하면 false를 반환합니다.
  3. using 문에 대한 요점을 참조하십시오. 적절한 진술을 사용하면 부담으로부터이 문제를 제거 할 수 있습니다. 당신 만 예외를 다시 발생하려면 시도 캐치를 할 필요가 없습니다 오라클
  4. 에서 ODP 제공자를 사용하는 경우
  5. 당신이 코드에 어떤 문제가 should't. 이 스택 트레이스에 throw e으로 중단되지 않고 최상위 레벨로 버블 링되게하고 finally 문에 필요한 모든 코드는 닫는 중괄호 사용에서 컴파일러에 의해 암시 적으로 추가됩니다.
+0

저는 SQL Server에 대한 더 많은 경험을 가지고 있습니다. 사실 SQL 문을 사용하여 항상 사용합니다. 무엇이 나에게 던져 졌는지는 OracleConnection도 OracleCommand도 IDisposable을 구현하지 않는다는 것입니다. 사용하는 진술이 여전히 처분되는 역할을합니까? 네임 스페이스 Oracle.DataAccess.클라이언트 { 공개 봉인 된 클래스 OracleConnection : DbConnection, ICloneable – Dimskiy

+0

@Dimskiy 예, 그들은 IDisposable을 구현합니다. 아마도 직접적인 것이 아니라 클래스에서 상속을 통한 것입니다. – mason

+0

@mason - 너 정말 옳아! 고맙습니다. 공용 추상 클래스 DbConnection : 구성 요소, IDbConnection, IDisposable – Dimskiy