1

OracleCommand.CommandTimeoutのODP.NETドキュメントは言う

デフォルトは 0 秒で、時間制限はありません。

コマンドの実行が完了する前に、指定されたタイムアウト値が期限切れになると、コマンドはキャンセルを試みます。キャンセルが成功した場合、ORA-01013: user requested cancel of current operation というメッセージとともに例外がスローされます。コマンドがエラーなしで時間内に実行された場合、例外はスローされません。

複数の OracleCommand オブジェクトが同じ接続を使用している状況では、いずれかの OracleCommand オブジェクトのタイムアウト期限により、単一の接続での実行が終了する場合があります。OracleCommand のタイムアウト期限がそれ自体のコマンド実行のみをキャンセルするようにするには、その OracleCommand が CommandTimeout プロパティを 0 より大きい値に設定する場合、接続ごとに 1 つの OracleCommand を使用するだけです。

しかし、このようなコードは機能します:

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使用していますがcmd2cmd1すでにタイムアウトしています (予想どおり)。ただし、ドキュメントによると、cmd2実行しないでください。ただし、例外なく実行され、他の行が適切に更新されます。

4

1 に答える 1

2

You do not have multiple commands running on the connection, you have two commands running sequentially, one after the other. When the first command times out, there is no other command pending on the connection. Your code does not submit the second command for execution until after the first command has either succeeded or has thrown an exception.

The last paragraph from the documentation you quoted should read: In a situation where multiple OracleCommand objects use the same connection simultaneously, ...

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
    }
}
于 2012-11-01T15:12:32.910 に答える