2010-12-13 17 views
2

一部のデータをoracle dbにバルク挿入しようとしています。私はドキュメンテーションの例に従った。このOracleのバルク挿入が機能しないのはなぜですか?

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(); 
} 

これはうまくいきません。データベースに何も挿入されていないため、エラーメッセージは表示されません。

一括挿入を使用しないと(すべてのデータテーブルから各行をforeachループし、各繰り返しでデータベースにDataRowを挿入すると)すべてが正常に機能します。

更新:私は提案に従って、私のパラメータに以下の変更を加えました。

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

アップデート2:

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

は、私はこのエラーを取得するODP.NETドライバは愚かである(私はexprectedとしてだけでは動作しません。)

これは

var names = new List<string>(); 
動作しません。

これはこれである必要があります

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

これが動作しない理由を確認していますが、それが動作するかどうかを確認するために最初に挿入し、行ごとにしようとしなければならないわけではありません。また、オラクルに十分なお金を支払ったことはありますか?それは問題の一部になる可能性があります。 ;) – poindexter12

+0

それは行ごとに動作し、私の雇用者は十分なお金を払っていた;) – mrt181

+0

これは、あなたが高い失踪を経験したときに起こることです。 –

答えて

1

私たちにリスト上のToArray()メソッドを持っていました。

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

バルク操作を機能させるには、パラメータCollectionTypeOracleCollectionType.PLSQLAssociativeArrayに設定する必要があります。

あなたがこれをspecificyすることを可能にする全くAdd()方法はありませんので、あなたがParameters.Add()への呼び出し後に次の行を追加する必要があります:

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

私はあなたにアプローチし、私の更新で終わった。それでも動作しませんが、今はエラーメッセージが表示されます。 – mrt181

+0

ArrayBindingを使用しています(コマンドをx回実行します。実行を開始する前にすべての値を指定します)。私はCollectionTypeまたはSizeプロパティを使用する必要はありません。 – mrt181

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; 
    } 
関連する問題