【问题标题】:What are the best practices working with Oracle.DataAccess.Client?使用 Oracle.DataAccess.Client 的最佳实践是什么?
【发布时间】:2018-03-13 23:19:27
【问题描述】:

我正在讨论一个较旧的应用程序的冗长数据访问代码。每个函数都在调用一个存储过程来从 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. 欢迎提出其他任何最佳做法/建议。

谢谢。

【问题讨论】:

  • 当你重新抛出一个捕获的异常时,不要做throw e;。只需执行 throw; 即可保留堆栈跟踪。
  • @mason - 谢谢

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


【解决方案1】:

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. 始终使用本地连接对象并将其包含在 using 声明以正确关闭和处置对象( OracleDataReader 和 OracleCommand 也是如此)。这将使您的服务器从与您的代码保持连接所需的内存和线程中释放出来,并且性能由 ADO.NET 提供程序启用的connection pooling 保证
  2. 不,不需要调用,也不需要调用 HasRows,如果您 计划循环结果。如果有,读者返回 false 没有行,或者如果您到达数据集的末尾
  3. 请参阅有关 using 语句的要点。正确的 using 语句将消除您的负担。
  4. 如果您使用 ODP,则此代码应该没有任何问题 来自 Oracle 的提供商
  5. 如果您只想重新抛出 例外。让它冒泡到上层没有 使用 throw e 中断堆栈跟踪,编译器将 finally 语句中所需的所有代码隐式添加到 using 右花括号中。

【讨论】:

  • 我对 Sql Server 有更多的经验,实际上我总是使用 using 语句。让我失望的是,OracleConnection 和 OracleCommand 都没有实现 IDisposable。 using 语句仍然可以完成他们的处理工作吗?命名空间 Oracle.DataAccess.Client { 公共密封类 OracleConnection : DbConnection, ICloneable
  • @Dimskiy 是的,他们确实实现了 IDisposable。也许不是直接的,而是通过继承一个类。
  • @mason - 你完全正确!谢谢你。公共抽象类 DbConnection:组件、IDbConnection、IDisposable
  • 以上几点在使用Oracle managed driver时适用吗?
  • 另一个问题是:如果我返回阅读器对象:OracleDataReader dataReader = cmd.ExecuteReader();返回数据读取器;连接和命令是否仍会关闭和处置?我应该在接收阅读器对象的调用者代码中迭代阅读器后处理阅读器吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-07
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多