使用 Oracle.DataAccess.Client 的最佳实践是什么?

What are the best practices working with Oracle.DataAccess.Client?

我正在查看一个较旧的应用程序的冗长数据访问代码。每个函数都在从 Oracle DB 调用一个存储过程以 select 某些东西。每个功能或多或少看起来像下面的代码:

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. 一些函数改用 class 级别的 OracleConnection 变量。什么是首选 - 功能级别或 class 级别变量?
  2. 是否需要检查dataReader == null?在 cmd.ExecuteReader() 调用后它会是 NULL 吗?
  3. 连接 Close/Dispose 和 reader Close/Dispose 的功能不同。 close/dispose 的正确 way/order 是什么?如果连接被释放,reader 不会自动 Close/Dispose 吗?
  4. 我希望在不久的将来 Oracle.ManagedDataAccess.Client 加入这个项目。此代码中的任何内容都会更改以与托管数据访问客户端一起使用吗?
  5. 任何其他的,任何最好的practices/suggestions都欢迎。

谢谢。

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 提供商
  2. 启用的 connection pooling 保证了性能
  3. 不,没有必要调用 HasRows 如果你 计划遍历结果。 reader returns false 如果有 没有行或者如果您到达数据集的末尾
  4. 参见using语句的要点。正确的 using 语句将使这个问题从你的负担中移除。
  5. 如果您使用 ODP,您应该不会对这段代码有任何问题 来自 Oracle 的提供商
  6. 如果你只想重新抛出 例外。让它冒泡到上层就可以了 使用 throw e 中断堆栈跟踪,finally 语句中所需的所有代码都由编译器在使用右大括号中隐式添加。