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

时间:2017-10-02 20:17:34

标签: c# oracle data-access-layer oracle-manageddataaccess

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

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. 欢迎任何其他事项,任何最佳做法/建议。
  6. 谢谢。

1 个答案:

答案 0 :(得分: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 计划循环结果。如果存在,则读者返回false 没有行或者如果到达数据集的末尾
  3. 请参阅有关using语句的观点。正确使用陈述将从您的负担中消除这个问题。
  4. 如果您使用ODP,则此代码不应该有任何问题 来自Oracle的提供商
  5. 如果您只想重新抛出,则无需尝试捕获 例外。只是让它冒泡到上层没有 使用throw e中断堆栈跟踪,并使用结束大括号中的编译器隐式添加finally语句中所需的所有代码。