sql >> データベース >  >> RDS >> Oracle

OracleDataReader.Readメソッドのタイムアウト

    これが私が最終的に採用した解決策です。これは、OracleDataReaderクラスの単なる拡張メソッドです。このメソッドには、タイムアウト値とパラメーターとしてのコールバック関数があります。コールバック関数は通常(常にではないにしても)OracleCommand.Cancelです。

    namespace ConsoleApplication1
    {
        public static class OracleDataReaderExtensions
        {
            public static bool Read(this OracleDataReader reader, int timeout, Action cancellationAction)
            {
                Task<bool> task = Task<bool>.Factory.StartNew(() => 
                    {
                        try
                        {
                            return reader.Read();
                        }
                        catch (OracleException ex)
                        {
                            // When cancellationAction is called below, it will trigger 
                            // an ORA-01013 error in the Read call that is still executing.
                            // This exception can be ignored as we're handling the situation
                            // by throwing a TimeoutException.
                            if (ex.Number == 1013)
                            {
                                return false;
                            }
                            else
                            {
                                throw;
                            }
                        }
                    });
    
                try
                {
                    if (!task.Wait(timeout))
                    {
                        // call the cancellation callback function (i.e. OracleCommand.Cancel())
                        cancellationAction();
    
                        // throw an exception to notify calling code that a timeout has occurred
                        throw new TimeoutException("The OracleDataReader.Read operation has timed-out.");
                    }
                    return task.Result;
                }
                catch (AggregateException ae)
                {
                    throw ae.Flatten();
                }
            }
        }
    }
    

    使用方法の例を次に示します。

    namespace ConsoleApplication1
    {
        class Program
        {
            static string constring = "User ID=xxxx; Password=xxxx; Data Source=xxxx;";
    
            static void Main(string[] args)
            {
                using (OracleConnection con = new OracleConnection(constring))
                using (OracleCommand cmd = new OracleCommand())
                {
                    cmd.Connection = con;
                    con.Open();
    
                    Console.WriteLine("Executing Query...");
    
                    string sql = "<some long running sql>";
                    cmd.CommandText = "PROC_A";
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    cmd.Parameters.Add(new OracleParameter("i_sql", OracleDbType.Varchar2) { Direction = ParameterDirection.Input, Value = sql });
                    cmd.Parameters.Add(new OracleParameter("o_cur1", OracleDbType.RefCursor) { Direction = ParameterDirection.Output });
    
                    try
                    {
                        // execute command and get reader for ref cursor
                        OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
    
                        // read first record; this is where the ref cursor SQL gets evaluated
                        Console.WriteLine("Reading first record...");
                        if (reader.Read(3000, cmd.Cancel)) { }
    
                        // read remaining records
                        Console.WriteLine("Reading records 2 to N...");
                        while (reader.Read(3000, cmd.Cancel)) { }
                    }
                    catch (TimeoutException ex)
                    {
                        Console.WriteLine("Exception: {0}", ex.Message);
                    }
    
                    Console.WriteLine("Press any key to continue...");
                    Console.Read();
                }
            }
        }
    }
    

    そして、これが出力の例です。

    Executing Query...
    Reading first record...
    Exception: The OracleDataReader.Read operation has timed-out.
    Press any key to continue...
    


    1. OBJECTPROPERTY()を使用して、オブジェクトがSQLServerのチェック制約であるかどうかを確認します

    2. MySQLでの削除後の自動インクリメント

    3. PostgreSQL 9.6:並列シーケンシャルスキャン

    4. 一意性の制約を処理するためにSQLiteUPDATEでORDERBYをシミュレートします