/// <summary> /// <paramref name="sqlString"/> 를 비동기 방식으로 실행하여, <see cref="Task{OracleDataReader}"/>를 반환받습니다. /// 받환받은 DataReader는 꼭 Dispose() 해 주어야 Connection이 닫힙니다. /// </summary> /// <param name="db">DAAB의 MySQL 용 Database</param> /// <param name="sqlString">실행할 SQL 문</param> /// <param name="parameters">Command Parameters</param> /// <returns><see cref="OracleDataReader"/>를 결과로 반환하는 <see cref="Task"/></returns> public static Task <OracleDataReader> ExecuteReaderBySqlStringAsync(this OdpNetDatabase db, string sqlString, params IAdoParameter[] parameters) { var cmd = GetSqlStringOracleCommand(db, sqlString); return(ExecuteReaderAsync(db, cmd, parameters)); }
/// <summary> /// <paramref name="spName"/> 를 비동기 방식으로 실행하여, <see cref="Task{OracleDataReader}"/>를 반환받습니다. /// 받환받은 DataReader는 꼭 Dispose() 해 주어야 Connection이 닫힙니다. /// </summary> /// <param name="db">DAAB의 MySQL 용 Database</param> /// <param name="spName">실행할 Procedure 명</param> /// <param name="parameters">Command Parameters</param> /// <returns><see cref="OracleDataReader"/>를 결과로 반환하는 <see cref="Task"/></returns> public static Task <OracleDataReader> ExecuteReaderByProcedureAsync(this OdpNetDatabase db, string spName, params IAdoParameter[] parameters) { var cmd = GetProcedureOracleCommand(db, spName, AdoTool.DEFAULT_DISCOVER_PARAMETER); return(ExecuteReaderAsync(db, cmd, parameters)); }
/// <summary> /// <paramref name="oracleCommand"/>를 실행하여, 결과 셋을 Persistent Object의 컬렉션으로 매핑합니다. /// </summary> /// <typeparam name="T">Persistent Object의 수형</typeparam> /// <param name="odpNetDatabase">OdpNetDatabase 인스턴스</param> /// <param name="oracleCommand">OracleCommand 인스턴스</param> /// <param name="mapObjectFactory">PersistentObject 생성 Factory</param> /// <param name="nameMap">NameMap 인스턴스</param> /// <param name="firstResult">첫번째 결과 인덱스 (0부터 시작)</param> /// <param name="maxResults">최대 결과 갯수</param> /// <param name="additionalMapping">부가적인 매핑 작업을 수행할 델리게이트</param> /// <param name="parameters">OracleCommand에 설정할 Parameter 정보</param> /// <returns>DataReader로부터 인스턴싱된 Persistent Object의 컬렉션을 결과로 반환하는 Task</returns> public static Task <IList <T> > ExecuteMapObject <T>(this OdpNetDatabase odpNetDatabase, OracleCommand oracleCommand, Func <T> mapObjectFactory, INameMap nameMap, int firstResult, int maxResults, Action <IDataReader, T> additionalMapping, params IAdoParameter[] parameters) { oracleCommand.ShouldNotBeNull("OracleCommand"); if (IsDebugEnabled) { log.Debug("DataReader를 열어, 수형[{2}]로 빌드합니다... CommandText=[{0}], Parameters=[{1}]", oracleCommand.CommandText, oracleCommand.Parameters.CollectionToString(), typeof(T).FullName); } return (ExecuteReaderAsync(odpNetDatabase, oracleCommand, parameters) .ContinueWith(task => { using (var reader = task.Result) return AdoTool.Map <T>(reader, mapObjectFactory, nameMap, firstResult, maxResults, additionalMapping); }, TaskContinuationOptions.ExecuteSynchronously)); }
private static void HandleConnectionError(OdpNetDatabase db, Exception ex, int?tryCount) { // NOTE: Oracle의 경우, Connection 에러가 나면, 대기 후에 접속하면 성공한다. 왜 그런지는 잘 모른다... // HINT: http://kyeomstar.tistory.com/160 // if (ex.Message.Contains("ORA-12519") || ex.Message.Contains("Unknown connection string parameter")) { if (log.IsWarnEnabled) { log.Warn("Database Connection 생성 및 Open 수행 시에 예외가 발생했습니다. ConnectionString=[{0}]", db.ConnectionString); log.Warn("Oracle 서버에 ALTER SYSTEM SET PROCESSES=500 SCOPE=SPFILE; 를 수행해 보세요. 기본 PROCESS 수가 40입니다. 이 값을 늘려보세요."); log.Warn(ex); } } else { if (log.IsErrorEnabled) { log.Error("Database Connection 생성 및 Open 수행 시에 예외가 발생했습니다. ConnectionString=[{0}]", db.ConnectionString); log.Error(ex); } } var timeout = Math.Min(MaxTimeout, Math.Abs(tryCount.GetValueOrDefault(1)) * 50); Thread.Sleep(timeout); }
/// <summary> /// <paramref name="cmd"/> 를 비동기 방식으로 실행하여, <see cref="Task{OdpNetDataReader}"/>를 반환받습니다. /// 받환받은 DataReader는 꼭 Dispose() 해 주어야 Connection이 닫힙니다. /// </summary> /// <param name="db">DAAB의 MySQL 용 Database</param> /// <param name="cmd">실행할 <see cref="OracleCommand"/> 인스턴스</param> /// <param name="parameters">Command Parameters</param> /// <returns><see cref="OracleDataReader"/>를 결과로 반환하는 <see cref="Task"/></returns> public static Task <OracleDataReader> ExecuteReaderAsync(this OdpNetDatabase db, OracleCommand cmd, params IAdoParameter[] parameters) { cmd.ShouldNotBeNull("cmd"); if (IsDebugEnabled) { log.Debug("OracleCommand.ExecuteReader를 비동기 방식으로 실행합니다. CommandText=[{0}], Parameters=[{1}]", cmd.CommandText, parameters.CollectionToString()); } if (parameters != null) { AdoTool.SetParameterValues(db, cmd, parameters); } db.PrepareCWRefCursor(cmd); var newConnectionCreated = false; if (cmd.Connection == null) { cmd.Connection = db.CreateOracleConnection(ref newConnectionCreated); } var commandBehavior = newConnectionCreated ? CommandBehavior.CloseConnection : CommandBehavior.Default; return(Task.Factory.StartNew(() => cmd.ExecuteReader(commandBehavior), TaskCreationOptions.PreferFairness)); }
/// <summary> /// 쿼리 문 또는 Procedure Name을 실행할 <see cref="OracleCommand"/>를 생성합니다. /// </summary> /// <param name="db">DAAB OdpNetDatabase</param> /// <param name="query">수행할 쿼리문 또는 Procedure Name</param> /// <param name="discoverParams">Procedure일 경우 Parameter 빌드</param> /// <returns>생성한 <see cref="OracleCommand"/></returns> /// <seealso cref="AdoRepositoryImplBase.GetCommand(string,bool)"/> public static OracleCommand GetOracleCommand(this OdpNetDatabase db, string query, bool discoverParams) { query.ShouldNotBeWhiteSpace("query"); return((AdoTool.IsSqlString(query)) ? GetSqlStringOracleCommand(db, query) : GetProcedureOracleCommand(db, query, discoverParams)); }
/// <summary> /// Oracle Connection을 비동기 방식으로 엽니다. /// </summary> /// <param name="db">DAAB OdpNetDatabase 인스턴스</param> /// <param name="newConnectionCreated">새로운 Connenction이 생성되었는지 여부</param> /// <returns>새로 연결된 <see cref="OracleConnection"/>의 인스턴스, 만약 연결에 실패했다면 null을 반환합니다.</returns> public static OracleConnection CreateOracleConnection(this OdpNetDatabase db, ref bool newConnectionCreated) { return ((OracleConnection) AdoTool.CreateTransactionScopeConnection(db, ref newConnectionCreated, database => ((OdpNetDatabase)database).OpenConnection(15))); }
/// <summary> /// 쿼리 문 <paramref name="sqlString"/>을 수행할 <see cref="OracleCommand"/>를 생성합니다. /// </summary> /// <param name="db">DAAB OdpNetDatabase</param> /// <param name="sqlString">수행할 쿼리문</param> /// <returns>생성한 <see cref="OracleCommand"/></returns> public static OracleCommand GetSqlStringOracleCommand(this OdpNetDatabase db, string sqlString) { if (IsDebugEnabled) { log.Debug("쿼리문을 수행할 OracleCommand를 생성합니다. sqlString=[{0}]", sqlString); } return((OracleCommand)db.GetSqlStringCommand(sqlString)); }
/// <summary> /// <paramref name="spName"/>을 ExecuteNonQuery 메소드로 비동기 실행을 하도록 하는 <see cref="Task{Int32}"/>를 빌드합니다. /// </summary> /// <param name="db">DAAB의 MySQL 용 Database</param> /// <param name="spName">실행할 프로시져 명</param> /// <param name="parameters">파리미터 정보</param> /// <returns>실행에 영향을 받은 행의 수를 결과로 가지는 <see cref="Task{Int32}"/></returns> public static Task <int> ExecuteNonQueryByProcedureAsync(this OdpNetDatabase db, string spName, params IAdoParameter[] parameters) { var cmd = GetProcedureOracleCommand(db, spName, AdoTool.DEFAULT_DISCOVER_PARAMETER); return (ExecuteNonQueryAsync(db, cmd, parameters) .ContinueWith(task => { With.TryAction(() => cmd.Dispose()); return task; }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap()); }
/// <summary> /// <paramref name="query"/> 를 비동기 방식으로 실행하여, Scalar 값을 반환하는 <see cref="Task{Object}"/>를 빌드합니다. /// </summary> /// <param name="db">DAAB의 MySQL 용 Database</param> /// <param name="query">실행할 쿼리문 또는 Procedure 명</param> /// <param name="parameters">Command Parameters</param> /// <returns>결과 Scalar 값을 가지는 Task의 인스턴스</returns> public static Task <object> ExecuteScalarAsync(this OdpNetDatabase db, string query, params IAdoParameter[] parameters) { var cmd = GetOracleCommand(db, query); return (ExecuteScalarAsync(db, cmd, parameters) .ContinueWith(task => { With.TryAction(() => cmd.Dispose()); return task; }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap()); }
/// <summary> /// Oracle 연결이 성공하지 못하는 경우가 많아, 재시도 횟수 만큼 간격을 두고 연결을 시도합니다. /// Oracle DB의 Process 수를 기본(40)에서 100 이상으로 늘려주면 연결이 성공할 확률이 높습니다. /// </summary> /// <param name="db">DAAB OdpNetDatabase 인스턴스</param> /// <param name="tryCount">연결 실패 시, 재 시도 횟수</param> /// <returns>새로 연결된 <see cref="OracleConnection"/>의 인스턴스, 만약 연결에 실패했다면 null을 반환합니다.</returns> public static OracleConnection OpenConnection(this OdpNetDatabase db, int tryCount) { // NOTE: Oracle의 경우 Connection이 연결 안 되는 에러(ORA-12519) 가 자주 발생한다. 그래서, 시간 Time을 두고, 재시도하도록 하였다. // HINT: http://forums.oracle.com/forums/thread.jspa?messageID=1145120, // HINT: http://kyeomstar.tistory.com/160 if (IsDebugEnabled) { log.Debug("Oracle Database를 연결하려고 합니다..."); } OracleConnection connection = null; for (var i = 0; i < tryCount; i++) { var count = i + 1; try { if (IsDebugEnabled) { log.Debug("OracleConnection을 생성하고, 비동기 방식으로 Open합니다. 시도 횟수=[{0}]", (i + 1)); } connection = (OracleConnection)db.CreateConnection(); connection.Open(); // DelegateAsync.Run(conn => conn.Open(), connection, null).WaitAsync(TimeSpan.FromSeconds(15)); if (connection.State == ConnectionState.Open) { if (IsDebugEnabled) { log.Debug("OracleConnection을 연결했습니다!!!"); } return(connection); } } catch (AggregateException age) { age.Handle(ex => { HandleConnectionError(db, ex, count); return(true); }); } catch (Exception ex) { HandleConnectionError(db, ex, count); } } Guard.Assert(connection != null && connection.State != ConnectionState.Closed, "Oracle Connection을 열지 못했습니다!!!"); return(connection); }
/// <summary> /// Prepares the CW ref cursor. /// </summary> /// <param name="command">The command.</param> /// <remarks> /// This is a private method that will build the Oracle package name if your stored procedure /// has proper prefix and postfix. /// This functionality is include for /// the portability of the architecture between SQL and Oracle datbase. /// This method also adds the reference cursor to the command writer if not already added. This /// is required for Oracle .NET managed data provider. /// </remarks> public static void PrepareCWRefCursor(this OdpNetDatabase db, OracleCommand command) { command.ShouldNotBeNull("command"); if (CommandType.StoredProcedure == command.CommandType) { // Check for ref. cursor in the command writer, if it does not exist, add a known reference cursor out of "cur_OUT" if (QueryProcedureNeedsCursorParameter(command)) { db.AddParameter(command, RefCursorName, OracleDbType.RefCursor, 0, ParameterDirection.Output, true, 0, 0, String.Empty, DataRowVersion.Default, Convert.DBNull); } } }
/// <summary> /// <paramref name="sqlString"/>을 ExecuteNonQuery 메소드로 비동기 실행을 하도록 하는 <see cref="Task{Int32}"/>를 빌드합니다. /// </summary> /// <param name="db">DAAB의 MySQL 용 Database</param> /// <param name="sqlString">실행할 쿼리문</param> /// <param name="parameters">파리미터 정보</param> /// <returns>실행에 영향을 받은 행의 수를 결과로 가지는 <see cref="Task{Int32}"/></returns> public static Task <int> ExecuteNonQueryBySqlStringAsync(this OdpNetDatabase db, string sqlString, params IAdoParameter[] parameters) { var cmd = GetSqlStringOracleCommand(db, sqlString); return (ExecuteNonQueryAsync(db, cmd, parameters) .ContinueWith(task => { With.TryAction(() => cmd.Dispose()); return task; }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap()); }
/// <summary> /// <paramref name="spName"/>를 비동기 방식으로 실행하여, 결과 셋을 <see cref="Task{DataTable}"/>로 반환합니다. /// </summary> public static Task <DataTable> ExecuteDataTableAsyncByProcedure(this OdpNetDatabase db, string spName, int firstResult, int maxResults, params IAdoParameter[] parameters) { var cmd = db.GetProcedureOracleCommand(spName, AdoTool.DEFAULT_DISCOVER_PARAMETER); return (ExecuteDataTableAsync(db, cmd, firstResult, maxResults, parameters) .ContinueWith(task => { With.TryAction(() => cmd.Dispose()); return task.Result; }, TaskContinuationOptions.ExecuteSynchronously)); }
/// <summary> /// Procedure <paramref name="spName"/>를 수행할 <see cref="OracleCommand"/> 를 생성합니다. /// </summary> /// <param name="db">DAAB OdpNetDatabase</param> /// <param name="spName">Procedure name</param> /// <param name="discoverParams">discover parameters</param> /// <returns>생성한 <see cref="OracleCommand"/></returns> public static OracleCommand GetProcedureOracleCommand(this OdpNetDatabase db, string spName, bool discoverParams) { if (IsDebugEnabled) { log.Debug("Procedure를 수행할 OracleCommand를 생성합니다. spName=[{0}], discoverParams=[{1}]", spName, discoverParams); } var cmd = db.GetStoredProcCommand(spName); if (discoverParams) { db.DiscoverParameters(cmd); } return((OracleCommand)cmd); }
/// <summary> /// <paramref name="sqlString"/>를 비동기 방식으로 실행하여, 결과 셋을 <see cref="Task{DataTable}"/>로 반환합니다. /// </summary> public static Task <DataTable> ExecuteDataTableAsyncBySqlString(this OdpNetDatabase db, string sqlString, int firstResult, int maxResults, params IAdoParameter[] parameters) { var cmd = db.GetSqlStringOracleCommand(sqlString); return (ExecuteDataTableAsync(db, cmd, firstResult, maxResults, parameters) .ContinueWith(task => { With.TryAction(() => cmd.Dispose()); return task; }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap()); }
/// <summary> /// Multi-ResultSet일 경우에 DataTable 컬렉션으로 반환합니다. /// </summary> public static Task <IList <DataTable> > ExecuteDataTableAsListAsync(this OdpNetDatabase db, OracleCommand cmd, int firstResult, int maxResults, params IAdoParameter[] parameters) { cmd.ShouldNotBeNull("cmd"); firstResult.ShouldBePositiveOrZero("firstResult"); maxResults.ShouldBePositiveOrZero("maxResults"); if (IsDebugEnabled) { log.Debug( "비동기 방식으로 ExecuteDataTableAsListAsync을 실행합니다... CommandText=[{0}], firstResult=[{1}], maxResults=[{2}], Parameters=[{3}]", cmd.CommandText, firstResult, maxResults, parameters.CollectionToString()); } return (ExecuteReaderAsync(db, cmd, parameters) .ContinueWith(task => { IList <DataTable> tables = new List <DataTable>(); using (var reader = task.Result) using (var adapter = new AdoDataAdapter(db.GetDataAdapter())) { do { var dataTable = new DataTable { Locale = CultureInfo.InvariantCulture }; adapter.Fill(new[] { dataTable }, reader, firstResult, maxResults); if (IsDebugEnabled) { log.Debug("비동기 방식으로 DataReader를 가져와 DataTable에 Load 했습니다!!!"); } tables.Add(dataTable); } while(reader.IsClosed == false && reader.NextResult()); } return tables; }, TaskContinuationOptions.ExecuteSynchronously)); }
/// <summary> /// <paramref name="cmd"/>를 비동기 방식으로 실행하여, 결과 셋을 <see cref="Task{DataTable}"/>로 반환합니다. /// </summary> public static Task <DataTable> ExecuteDataTableAsync(this OdpNetDatabase db, OracleCommand cmd, int firstResult, int maxResults, params IAdoParameter[] parameters) { cmd.ShouldNotBeNull("cmd"); firstResult.ShouldBePositiveOrZero("firstResult"); maxResults.ShouldBePositiveOrZero("maxResults"); if (IsDebugEnabled) { log.Debug("비동기 방식으로 ExecuteDataTable을 실행합니다.. CommandText=[{0}], firstResult=[{1}], maxResults=[{2}], Parameters=[{3}]", cmd.CommandText, firstResult, maxResults, parameters.CollectionToString()); } return (ExecuteReaderAsync(db, cmd, parameters) .ContinueWith(task => AdoTool.BuildDataTableFromDataReader(db, task.Result, firstResult, maxResults), TaskContinuationOptions.ExecuteSynchronously)); }
/// <summary> /// <paramref name="cmd"/> 를 비동기 방식으로 실행하여, Scalar 값을 반환하는 <see cref="Task{Object}"/>를 빌드합니다. /// </summary> /// <param name="db">DAAB의 MySQL 용 Database</param> /// <param name="cmd">실행할 OracleCommand 인스턴스</param> /// <param name="parameters">Command Parameters</param> /// <returns>Scalar 값을 결과로 가지는 Task의 인스턴스</returns> public static Task <object> ExecuteScalarAsync(this OdpNetDatabase db, OracleCommand cmd, params IAdoParameter[] parameters) { cmd.ShouldNotBeNull("cmd"); if (IsDebugEnabled) { log.Debug("OracleCommand.ExecuteScalar를 비동기 방식으로 실행합니다... CommandText=[{0}], Parameters=[{1}]", cmd.CommandText, parameters.CollectionToString()); } var newConnectionCreated = false; if (cmd.Connection == null) { cmd.Connection = db.CreateOracleConnection(ref newConnectionCreated); } if (parameters != null) { AdoTool.SetParameterValues(db, cmd, parameters); } db.PrepareCWRefCursor(cmd); return (Task.Factory .StartNew(() => cmd.ExecuteScalar(), TaskCreationOptions.PreferFairness) .ContinueWith(task => { if (newConnectionCreated) { AdoTool.ForceCloseConnection(cmd); } return task; }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap()); }
/// <summary> /// <paramref name="query"/> 를 비동기 방식으로 실행하여, <see cref="Task{OracleDataReader}"/>를 반환받습니다. /// 받환받은 DataReader는 꼭 Dispose() 해 주어야 Connection이 닫힙니다. /// </summary> /// <param name="db">DAAB의 MySQL 용 Database</param> /// <param name="query">실행할 SQL 문</param> /// <param name="parameters">Command Parameters</param> /// <returns><see cref="OracleDataReader"/>를 결과로 반환하는 <see cref="Task"/></returns> public static Task <OracleDataReader> ExecuteReaderAsync(this OdpNetDatabase db, string query, params IAdoParameter[] parameters) { var cmd = GetOracleCommand(db, query); return(ExecuteReaderAsync(db, cmd, parameters)); }
/// <summary> /// <paramref name="sqlString"/>를 비동기 방식으로 실행하여, 결과 셋을 <see cref="Task{DataTable}"/>로 반환합니다. /// </summary> public static Task <DataTable> ExecuteDataTableAsyncBySqlString(this OdpNetDatabase db, string sqlString, params IAdoParameter[] parameters) { return(ExecuteDataTableAsyncBySqlString(db, sqlString, 0, 0, parameters)); }
/// <summary> /// <paramref name="spName"/>를 비동기 방식으로 실행하여, 결과 셋을 <see cref="Task{DataTable}"/>로 반환합니다. /// </summary> public static Task <DataTable> ExecuteDataTableAsyncByProcedure(this OdpNetDatabase db, string spName, params IAdoParameter[] parameters) { return(ExecuteDataTableAsyncByProcedure(db, spName, 0, 0, parameters)); }
/// <summary> /// <paramref name="cmd"/>를 비동기 방식으로 실행하여, 결과 셋을 <see cref="Task"/>로 반환합니다. /// </summary> public static Task <DataTable> ExecuteDataTableAsync(this OdpNetDatabase db, OracleCommand cmd, params IAdoParameter[] parameters) { return(ExecuteDataTableAsync(db, cmd, 0, 0, parameters)); }
/// <summary> /// 쿼리 문 또는 Procedure Name을 실행할 <see cref="OracleCommand"/>를 생성합니다. /// </summary> /// <param name="db">DAAB db</param> /// <param name="query">수행할 쿼리문 또는 Procedure Name</param> /// <returns>생성한 <see cref="OracleCommand"/></returns> public static OracleCommand GetOracleCommand(this OdpNetDatabase db, string query) { query.ShouldNotBeWhiteSpace("query"); return(GetOracleCommand(db, query, AdoTool.DEFAULT_DISCOVER_PARAMETER)); }
/// <summary> /// <paramref name="query"/>를 비동기 방식으로 실행하여, 결과 셋을 <see cref="Task{DataTable}"/>로 반환합니다. /// </summary> public static Task <DataTable> ExecuteDataTableAsync(this OdpNetDatabase db, string query, params IAdoParameter[] parameters) { return(ExecuteDataTableAsync(db, query, 0, 0, parameters)); }