【问题标题】:OracleCommand timeoutOracle命令超时
【发布时间】:2014-03-07 04:32:27
【问题描述】:

ODP.NET documentation for OracleCommand.CommandTimeout 说

默认为 0 秒,没有时间限制。

当指定的超时值在命令执行之前到期时 完成后,该命令将尝试取消。如果取消是 成功,抛出异常,消息为 ORA-01013: user 请求取消当前操作。如果命令及时执行 没有任何错误,不会抛出异常。

在多个 OracleCommand 对象使用相同的情况下 连接,OracleCommand 对象之一的超时到期 可以终止单个连接上的任何执行。做 OracleCommand 的超时到期只取消它自己的命令 执行,只需为每个连接使用一个 OracleCommand OracleCommand 将 CommandTimeout 属性设置为大于 0.

但是这样的代码可以工作:

static void Main(string[] args)
{
    OracleConnection conn = null;
    try
    {
        string connString =
            "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=myOracleHost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=myServiceName)));User Id=system;Password=admin;Pooling = False;";
        string cmdString1 = "UPDATE employee SET empname = 'temp1' where id = 1";
        string cmdString2 = "Update employee set empname = 'temp2' where id = 2";
        conn = new OracleConnection(connString);
        var cmd1 = new OracleCommand(cmdString1, conn);
        cmd1.CommandTimeout = 30;
        var cmd2 = new OracleCommand(cmdString2, conn);
        cmd2.CommandTimeout = 30;
        conn.Open();
        try
        {
            //Locked the row with ID 1 with an uncommitted update operation outside this code
            cmd1.ExecuteNonQuery();
        }
        catch (Exception exception)
        {
            //Exception ORA-01013 Thrown as expected
        }
        try
        {
            //As per the documentation, this should not also work since this command object also uses the same connection as above and it timed out in the query above
            cmd2.ExecuteNonQuery();
            //But this still works fine. 
        }
        catch (Exception)
        {
            //no exception
        }
    }
    finally
    {
        conn.Close();
    }
}

我对两个命令对象使用相同的OracleConnection 对象-cmd1 和cmd2,并且cmd1 已经超时(如预期的那样)。 但是,根据文档,cmd2 也不应该运行。但它仍然毫无例外地运行并正确更新另一行。

【问题讨论】:

    标签: .net oracle odp.net oraclecommand


    【解决方案1】:

    您没有在连接上运行多个命令,您有两个命令依次运行,一个接一个。当第一个命令超时时,连接上没有其他命令挂起。在第一个命令成功或引发异常之前,您的代码不会提交第二个命令以供执行。

    您引用的文档的最后一段应为:在多个 OracleCommand 对象同时使用同一连接的情况下,...

    static void Main(string[] args)
    {
        using (var conn = new OracleConnection("Pooling=False;...")) // why?
        using (var cmd1 = conn.CreateCommand())
        using (var cmd2 = conn.CreateCommand())
        {
            cmd1.CommandText = "UPDATE employee SET empname = 'temp1' WHERE id = 1";
            cmd2.CommandText = "UPDATE employee SET empname = 'temp2' WHERE id = 2";
            cmd1.CommandTimeout = 30;
            cmd2.CommandTimeout = 30;
    
            conn.Open();
    
            // there are no commands on conn yet
    
            try { cmd1.ExecuteNonQuery(); } // cmd1 is the only command on conn
            catch (OracleException) { } // if timeout, no other command affected
    
            // cmd1 is no longer on conn
    
            try { cmd2.ExecuteNonQuery(); } // cmd2 is the only command on conn
            catch (OracleException) { } // if timeout, no other command affected
    
            // cmd2 is no longer on conn
        }
    }
    

    【讨论】:

    • Pooling 是错误的,因为它是一项夜间工作(服务器用于单一地理位置,预计夜间负载接近零),因此在以下情况下设置 Pooling 似乎是一个更好的选择与验证从池返回的连接所涉及的开销相比。
    猜你喜欢
    • 1970-01-01
    • 2021-09-06
    • 2013-04-03
    • 2013-09-30
    • 2019-12-06
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多