Ваш пакет принимает не ассоциативный массив PLSQL, а отдельные элементы.Я полагаю, что вы пытаетесь сделать вставку массива (которая в значительной степени упаковывает в C # ваш код X раз и массово отправляет его в базу данных для выполнения работы)
эта ссылка напрямую описываетчто вы хотите сделать: http://www.oracle.com/technology/sample_code/tech/windows/odpnet/howto/arraybind/index.html
(я сделал несколько изменений в вашем коде, а именно:
- удалил ассоциированный массив pl / sql тип элемента
- добавлен ArrayBindCount
- Вы использовали анонимный блок, заменили его на вызов хранимой процедуры
1 & 2 должны решить вашу проблему, в то время как # 3 - больше синтаксического сахара
однако, этот код не проверен, но работает
class Program
{
private static string connString = @"User Id=User; Password=root; Data Source=SOURCE";
private static List<string> forecast_types = new List<string> { "a", "b" };
private static List<double> forecast_values = new List<double> { .1, .2 };
static void Main(string[] args)
{
using (var con = new OracleConnection(connString))
{
//string query = "BEGIN curves.sp_insert(:forecast_types, :forecast_values); END;";
string query = "curves.sp_insert";
try
{
con.Open();
using (OracleCommand cmd = con.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.StoredProcedure; // CommandType.Text; //you can change this to a stored procedure and not utilize the anonymous block
cmd.ArrayBindCount = 2; //use ArrayBindCount
cmd.BindByName = true;
cmd.Parameters.Add(new OracleParameter
{
ParameterName = ":forecast_types",
OracleDbType = OracleDbType.Varchar2,
Value = forecast_types.ToArray(),
Direction = ParameterDirection.Input,
//CollectionType = OracleCollectionType.PLSQLAssociativeArray //this is not needed
}
);
cmd.Parameters.Add(new OracleParameter
{
ParameterName = ":forecast_values",
OracleDbType = OracleDbType.Double,
Value = forecast_values.ToArray(),
Direction = ParameterDirection.Input,
//CollectionType = OracleCollectionType.PLSQLAssociativeArray //this is not needed
}
);
cmd.ExecuteNonQuery();
}
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex);
}
finally
{
con.Close();
}
}
}
}
РЕДАКТИРОВАТЬ
Я заметил, что вы сделали попробуйте передать ассоциативный массив (я вижу создание типа зацикливания в процедуре).
Это тоже не сложно сделать. На этом замечании вы на правильномtrack.
вам нужно изменить пакет, чтобы в него передавались массивы.через параметры CREATE ИЛИ ЗАМЕНИТЬ ПАКЕТНЫЕ ИЗОБРАЖЕНИЯ КАК тип t_forecast_values является таблицей test.column2% TYPE index by varchar (20);assoc_array t_forecast_values;
--need to create an assoc.array for numbers
type t_numbera_values is table of test.column2%TYPE index by number(10);
--changed to accept the assoc.array to varchar and numbers
procedure sp_insert (param1 in t_forecast_values, param2 in t_numbera_values);
END CURVES;
create or replace
PACKAGE BODY CURVES AS
--changed to accept the assoc.array to varchar and numbers
PROCEDURE SP_INSERT (PARAM1 IN T_FORECAST_VALUES, PARAM2 IN T_NUMBERA_VALUES) AS
BEGIN
--assoc_array(param1) := param2; /*not sure what the intent of this was...*/
DECLARE PRIMARYKEY NUMBER(10);
BEGIN
FOR i IN PARAM1.first .. PARAM1.last
LOOP
SELECT seq_curves.nextval INTO primarykey FROM dual;
INSERT INTO TEST (COLUMN1, COLUMN2, COLUMN3)
VALUES (primarykey, PARAM1(i), PARAM2(i));
INSERT INTO TEST2 (column1, column2)
VALUES (PRIMARYKEY, 'default');
END LOOP ;
--assuming you are going to add error handling here
END;
end sp_insert;
END CURVES;
, и вам нужно будет добавить параметр размера в список параметров как таковой
class Program
{
private static string connString = @"User Id=User; Password=root; Data Source=SOURCE";
private static List<string> forecast_types = new List<string> { "a", "b" };
private static List<double> forecast_values = new List<double> { .1, .2 };
static void Main(string[] args)
{
using (var con = new OracleConnection(connString))
{
string query = "curves.sp_insert";
try
{
con.Open();
using (OracleCommand cmd = con.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = true;
cmd.Parameters.Add(new OracleParameter
{
ParameterName = "param1",
OracleDbType = OracleDbType.Varchar2,
Value = forecast_types.ToArray(),
Direction = ParameterDirection.Input,
CollectionType = OracleCollectionType.PLSQLAssociativeArray,
Size = 2
}
);
cmd.Parameters.Add(new OracleParameter
{
ParameterName = "param2",
OracleDbType = OracleDbType.Double,
Value = forecast_values.ToArray(),
Direction = ParameterDirection.Input,
CollectionType = OracleCollectionType.PLSQLAssociativeArray,
Size = 2
}
);
cmd.ExecuteNonQuery();
}
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex);
}
finally
{
con.Close();
}
}
}
}
, чтобы получить отличный пример этого перехода к ORACLE_HOME \ odp.net \samples \ 2.x \ AssocArray \ AssocArray.cs он делает именно то, что вам нравится
весь приведенный выше код не протестирован, но должен вывести вас на правильный путь, либо из привязки массива (первый пример), либо путем передачи вмассив pl / sql (второй пример)