2017-10-02 13 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. あなたはOracleの
  5. からODP プロバイダを使用する場合にのみ 例外を再スローする場合にtryキャッチを持ってする必要はありません。このコードに問題がありshould't。 がスタックトレースを中断してthrow eにすることなく、上位レベルまでバブルアップさせて、finallyステートメントで必要なすべてのコードを暗黙的にコンパイラによって使用中の中かっこに追加します。
+0

私はSql Serverの経験が豊富ですが、実際には常にステートメントを使用しています。ここでは、OracleConnectionもOracleCommandもIDisposableを実装していないということです。使用しているステートメントは処分の仕事をしていますか? 名前空間Oracle.DataAccess。クライアント { 公開密封クラスOracleConnection:DbConnection、ICloneable – Dimskiy

+0

@Dimskiyはい、IDisposableを実装しています。おそらく直接ではなく、それを継承するクラスから継承します。 – mason

+0

@mason - あなたは絶対に正しいです!ありがとうございました。 public abstract class DbConnection:コンポーネント、IDbConnection、IDisposable – Dimskiy

関連する問題