프로그래밍/C#

[C#] Oracle Bulk Insert

흔한티벳여우 2022. 4. 1. 08:12
반응형
public class TableA
{
	public string A { get; set; }
	public string B { get; set; }
	public string C { get; set; }
}

 만약 위와 같은 테이블 레이아웃을 가지는 Bulk data 가 있다고 하자. 만약 한 두건 정도면 쿼리로 넘기면 되지만 만건 10만건 정도 되는 데이터를 넘길때는 OracleParameter와 ArrayBindCount를 이용하여 한꺼번에 보낸다.

 

아래의 코드는 1000건씩 Insert하는 코드를 첨부하였다.

public async Task<bool> BulkInsert(List<TableA> result)
{
    using (OracleConnection conn = new OracleConnection(_connectInfo))
    {
        // 연결
        await conn.OpenAsync();

        OracleTransaction transaction;
        transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);

        var rawList = result.ToList();

        try
        {
            while (rawList.Count != 0)
            {
                List<OracleParameter> parameters = new List<OracleParameter>();

                int maxCount = rawList.Count > 1000 ? 1000 : rawList.Count;

                string[] a = new string[maxCount];
                string[] b = new string[maxCount];
                string[] c = new string[maxCount];

				string[] a = rawList.Select(m => m.A).Take(maxCount).ToArray();
				string[] b = rawList.Select(m => m.B).Take(maxCount).ToArray();
				string[] c = rawList.Select(m => m.C).Take(maxCount).ToArray();
				
				rawList.RemoveRange(0, maxCount);

                parameters.Add(new OracleParameter(":A", OracleDbType.Varchar2) { Value = a, Direction = ParameterDirection.Input });
                parameters.Add(new OracleParameter(":B", OracleDbType.Varchar2) { Value = b, Direction = ParameterDirection.Input });
                parameters.Add(new OracleParameter(":C", OracleDbType.Varchar2) { Value = c, Direction = ParameterDirection.Input });

                string query = "INSERT INTO TABLEA (A,B,C) VALUES (:A,:B,:C)";
                using (OracleCommand cmd = new OracleCommand(query,conn))
                {
                    cmd.CommandType = CommandType.Text;
                    cmd.BindByName = true;
                    cmd.ArrayBindCount = maxCount;
                    foreach (var item in parameters)
                    {
                        cmd.Parameters.Add(item);
                    }
                    await cmd.ExecuteNonQueryAsync();
                    cmd.Parameters.Clear();
                    cmd.Dispose();
                }

                parameters.Clear();

                Console.WriteLine($"{rawList.Count}/{result.Count}");
            }
            transaction.Commit();
        }
        catch (Exception ex)
        {
            transaction.Rollback();
            Console.WriteLine(ex.ToString());
            return false;
        }

        conn.Close();
        conn.Dispose();
    }
    return true;
}
반응형