>

Oracle DB에 일부 데이터를 대량 삽입하려고합니다. 설명서의 예제를 따랐습니다.

this.DataBaseAccess = new OracleConnection(connString);
var dataAdapter = new OracleDataAdapter();
var insertCmd = DataBaseAccess.CreateCommand();
insertCmd.CommandType = CommandType.Text;
insertCmd.BindByName = true;
var names = new List<string>();
foreach (DataTable table in product.Contracts.Tables)
{
    foreach (DataRow row in table.Rows)
    {
        names.Add(row["Contract"].ToString());
    }
    const string InsertContracts = "merge into CONTRACT t " +
                                   "using " +
                                   "(select :name NAME from dual) s " +
                                   "on (t.NAME = s.NAME) " +
                                   "when not matched then " +
                                   "insert (t.NAME) " +
                                   "values (s.NAME)";
    insertCmd.CommandText = InsertContracts;
    insertCmd.ArrayBindCount = table.Rows.Count;
    insertCmd.Parameters.Add(":name", OracleDbType.Varchar2, names, ParameterDirection.Input);
    dataAdapter.InsertCommand = insertCmd;
    this.DataBaseAccess.Open();
    insertCmd.ExecuteNonQuery();
    this.DataBaseAccess.Close();
}

잘 작동하지 않습니다. 데이터베이스에 아무것도 삽입되지 않았습니다. 오류 메시지가 표시되지 않습니다.

대량 삽입을 사용하지 않으면 모든 것이 잘 작동합니다 (대신 내 DataTables의 각 행을 foreach-loop하고 각 반복마다 DataRow를 데이터베이스에 삽입합니다).

업데이트 : 제안 사항을 따르고 매개 변수를 다음과 같이 변경했습니다.

var nameParam = new OracleParameter
    {
        ParameterName = ":name",
        OracleDbType = OracleDbType.Varchar2,
        Value = names,
        Size = table.Rows.Count,
        CollectionType = OracleCollectionType.PLSQLAssociativeArray,
        Direction = ParameterDirection.Input
    };

이 오류가 발생합니다 :

System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Array'.
at Oracle.DataAccess.Client.OracleParameter.SetStatus(Int32 arraySize)
at Oracle.DataAccess.Client.OracleParameter.ResetCtx(Int32 arraySize)
at Oracle.DataAccess.Client.OracleParameter.PreBind(OracleConnection conn, IntPtr errCtx, Int32 arraySize)
at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()
at Gateway.DataGateway.Import(String connString, Product product) in \path\share$\Visual Studio 2010\Projects\ImportData-trunk\Gateway\DataGateway.Sql.cs:line 196

UPDATE2 : ODP.NET 드라이버가 멍청합니다 (예기 한대로 작동하지 않습니다.)

이 작동하지 않습니다

var names = new List<string>();

이것이어야합니다

var names = new string[table.Rows.Count];


  • 답변 # 1

    CollectionType 매개 변수를 설정해야합니다   OracleCollectionType.PLSQLAssociativeArray 에 재산  대량 작업을 수행 할 수 있습니다.

    Add() 가 없기 때문에  이것을 구체적으로 지정할 수있는 방법을 사용하려면 Parameters.Add() 를 호출 한 후 다음 줄을 추가해야합니다 :

    insertCmd.Parameters[0].CollectionType = OracleCollectionType.PLSQLAssociativeArray
    
    

  • 답변 # 2

    private void BulkCopy(List<test_bulk> lsttest_bulk)
        {       
            try
            {
                //ConnectionString = String.Format("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={0})(PORT={1})))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={2})));User Id={3};Password={4};", "ServerAddress", "PortAddress", "DatabaseName", "Username", "Password");
                ConnectionString = String.Format("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={0})(PORT={1})))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={2})));User Id={3};Password={4};", "ServerAddress", "PortAddress", "DatabaseName", "Username", "Password");
    
                OracleConnection oraConn = new OracleConnection(ConnectionString);
                oraConn.Open();
                OracleCommand oraCMD = new OracleCommand();
                oraCMD.Connection = oraConn;
    
                var oracleBulkCopy = new OracleBulkCopy(oraConn)
                {
                    DestinationTableName = "test_bulk",
                    BulkCopyOptions = OracleBulkCopyOptions.UseInternalTransaction
                };
                    DataTable oDataTable = GetDataTableFromObjects<test_bulk>(lsttest_bulk);
                    oracleBulkCopy.WriteToServer(oDataTable);
                    oracleBulkCopy.Dispose();
            }
            catch(Exception ex)
            {
                Console.WriteLine("failed to write:\t{0}", ex.Message);
            }
        }
    
        public static DataTable GetDataTableFromObjects<TDataClass>(List<TDataClass> dataList)
        where TDataClass : class
        {
            Type t = typeof(TDataClass);
            DataTable dt = new DataTable(t.Name);
            foreach (PropertyInfo pi in t.GetProperties())
            {
                dt.Columns.Add(new DataColumn(pi.Name));
            }
            if (dataList != null)
            {
                foreach (TDataClass item in dataList)
                {
                    DataRow dr = dt.NewRow();
                    foreach (DataColumn dc in dt.Columns)
                    {
                        dr[dc.ColumnName] =
                          item.GetType().GetProperty(dc.ColumnName).GetValue(item, null);
                    }
                    dt.Rows.Add(dr);
                }
            }
            return dt;
        }
    
    

  • 답변 # 3

    List의 ToArray () 메소드가 필요했습니다.

    insertCmd.Parameters.Add(":name", OracleDbType.Varchar2, names.ToArray(), ParameterDirection.Input);
    
    

  • 이전 Win XP의 명령 줄 유틸리티 프록시
  • 다음 sql - sqlite에서 알 수없는 값을 연결