我正在尝试将一些数据批量插入到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中遍历每一行并在每次迭代时将DataRow插入数据库)。
更新:我已按照建议对我的参数进行了以下更改。
var nameParam = new OracleParameter
{
ParameterName = ":name",
OracleDbType = OracleDbType.Varchar2,
Value = names,
Size = table.Rows.Count,
CollectionType = OracleCollectionType.PLSQLAssociativeArray,
Direction = ParameterDirection.Input
};
我收到此错误:
System.InvalidCastException:无法将“System.String”类型的对象强制转换为“System.Array”类型。
在Oracle.DataAccess.Client.OracleParameter.SetStatus(Int32 arraySize)
在Oracle.DataAccess.Client.OracleParameter.ResetCtx(Int32 arraySize)
在Oracle.DataAccess.Client.OracleParameter.PreBind(OracleConnection conn,IntPtr errCtx,Int32 arraySize)
在Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()
位于\ path \ share $ \ Visual Studio 2010 \ Projects \ ImportData-trunk \ Gateway \ DataGateway.Sql.cs:第196行中的Gateway.DataGateway.Import(String connString,Product product)
UPDATE2:ODP.NET驱动程序是愚蠢的(只是因为我的exprected不起作用;)
这不起作用
var names = new List<string>();
必须是这个
var names = new string[table.Rows.Count];
答案 0 :(得分:2)
您需要将参数CollectionType
属性设置为OracleCollectionType.PLSQLAssociativeArray
才能使批量操作正常运行。
由于没有Add()
方法允许您对此进行说明,因此您必须在调用Parameters.Add()
后添加以下行:
insertCmd.Parameters[0].CollectionType = OracleCollectionType.PLSQLAssociativeArray
答案 1 :(得分: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;
}
答案 2 :(得分:1)
我不得不在List上使用ToArray()方法。
insertCmd.Parameters.Add(":name", OracleDbType.Varchar2, names.ToArray(), ParameterDirection.Input);