Почему эта вставка оракула не работает? - PullRequest
2 голосов
/ 13 декабря 2010

Я пытаюсь массово вставить некоторые данные в базу данных оракула. Я последовал примеру в документации.

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

Ну, это не работает. Ничего не вставлено в базу данных, я не получаю никаких сообщений об ошибках.

Все работает нормально, когда я не использую массовую вставку (вместо этого я выполняю циклический цикл по каждой строке из моей таблицы данных и вставляю 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 ()
в Gateway.DataGateway.Import (String connString, Product product) в \ path \ share $ \ Visual Studio 2010 \ Projects \ ImportData-trunk \ Gateway \ DataGateway.Sql.cs: строка 196

ОБНОВЛЕНИЕ2: Драйвер ODP.NET тупой (просто не работает, как я понял;)

это не работает

var names = new List<string>();

должно быть это

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

Ответы [ 3 ]

2 голосов
/ 24 июля 2012
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 голосов
/ 13 декабря 2010

Вам необходимо установить для параметра CollectionType свойство значение OracleCollectionType.PLSQLAssociativeArray, чтобы заставить массовые операции работать.

Поскольку не существует метода Add(), который бы позволил вам это конкретно указать, вам необходимо добавитьследующая строка после звонка Parameters.Add():

insertCmd.Parameters[0].CollectionType = OracleCollectionType.PLSQLAssociativeArray
1 голос
/ 21 января 2011

У меня был метод ToArray () в Списке.

insertCmd.Parameters.Add(":name", OracleDbType.Varchar2, names.ToArray(), ParameterDirection.Input);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...