Можно ли вызвать хранимую процедуру из приложения .net, передавая список массива строки или целого числа в качестве параметра - PullRequest
1 голос
/ 18 апреля 2011

Я знаю, что это возможно из базы данных для создания типа и отправки его в хранимую процедуру в качестве параметра.

Но, похоже, он не работает с приложением .net, будь то ADO.net или Nhibernate. Версия Oracle

10г.

ODP.net

11,2

Версия сборки : 2.112.2.0

Версия продукта : 2.112.2.0

DLL : Oracle.DataAccess.dll

Тип, созданный в ORACLE

создать или заменить TYPE NUMBER_ARRAY IS TABLE OF NUMBER;

Хранимая процедура
создать или заменить PROCEDURE odp_varray_sample_proc_test (параметр IN NUMBER_ARRAY) ЯВЛЯЕТСЯ НАЧАТЬ вставить в сотрудника (emp_id, emp_name, emp_password, is_captain, no_of_mom) значения (45455, «Адам», «123545», «Y», 0); END odp_varray_sample_proc_test;

C # код

ISQLQuery query = eventhistorysession.CreateSQLQuery ("BEGIN odp_varray_sample_proc_test (: param); END;");

query.SetParameter ("param", новый Int64 [] {259688}, новый Int64ArrayType ());

int final = query.ExecuteUpdate ();

Исключение

NHibernate.Exceptions.GenericADOException был пойман Сообщение = "не удалось выполнить собственный запрос на массовые манипуляции: BEGIN odp_varray_sample_proc_test (: param); END; [SQL: BEGIN odp_varray_sample_proc_test (: p0); END;]" Источник = "NHibernate" SqlString = "BEGIN odp_varray_sample_proc_test (: p0); END;" Трассировки стека: в NHibernate.Engine.Query.NativeSQLQueryPlan.PerformExecuteUpdate (QueryParameters queryParameters, сеанс ISessionImplementor) в NHibernate.Impl.SessionImpl.ExecuteNativeUpdate (NativeSQLQuerySpecification nativeQuerySpecification, QueryParameters queryParameters) в NHibernate.Impl.SqlQueryImpl.ExecuteUpdate () в TestDatabase.Program.InsertNhibernate () в C: \ Jaroori Kachra \ TestDatabase \ TestDatabase \ Program.cs: строка 184 InnerException: Oracle.DataAccess.Client.OracleException Сообщение = "ORA-06550: строка 1, столбец 7: \ nPLS-00306: неверный номер или типы аргументов при вызове 'ODP_VARRAY_SAMPLE_PROC_TEST' \ nORA-06550: строка 1, столбец 7: \ nPL / SQL: оператор игнорируется" Источник = "Поставщик данных Oracle для .NET" ErrorCode = -2147467259 DataSource = "RACDV" Number = 6550 Процедура = «» Трассировки стека: в Oracle.DataAccess.Client.OracleException.HandleErrorHelper (Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx * pOpoSqlValCtx, Object src, строковая процедура, логический bCheck) в Oracle.DataAccess.Client.OracleException.HandleError (Int32 errCode, OracleConnection conn, строковая процедура, IntPtr opsErrCtx, OpoSqlValCtx * pOpoSqlValCtx, Object src, Boolean bCheck) в Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery () в NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery (IDbCommand cmd) в NHibernate.Engine.Query.NativeSQLQueryPlan.PerformExecuteUpdate (QueryParameters queryParameters, сеанс ISessionImplementor) InnerException:

Ответы [ 2 ]

1 голос
/ 18 апреля 2011

Пример типа и процедуры в Oracle:

TYPE NUMBER_ARRAY IS TABLE OF NUMBER NOT NULL INDEX BY PLS_INTEGER;
PROCEDURE procedure_name(array IN NUMBER_ARRAY);

Пример вызова хранимой процедуры с помощью NHibernate:

ISQLQuery query = _session.CreateSQLQuery("BEGIN procedure_name(:array); END;"
query.SetParameter("array", array, new Int64ArrayType());
query.ExecuteUpdate();

Вам нужно реализовать этот Int64ArrayType самостоятельно:

[Serializable]
public class Int64ArrayType : ImmutableType {
  public Int64ArrayType()
     : base(SqlTypeFactory.Int64) {
  }

  public override object Get(System.Data.IDataReader rs, string name) {
     return rs[name];
  }

  public override object Get(System.Data.IDataReader rs, int index) {
     return rs[index];
  }

  public override void Set(System.Data.IDbCommand cmd, object value, int index) {
     OracleCommand orclCmd = (OracleCommand)cmd;
     orclCmd.Parameters[index].OracleDbType = OracleDbType.Int64;
     orclCmd.Parameters[index].CollectionType = OracleCollectionType.PLSQLAssociativeArray;
     orclCmd.Parameters[index].Value = value;
  }

  public override string ToString(object val) {
     return String.Join(";", (object[])val);
  }

  public override string Name {
     get { return "Int64ArrayType"; }
  }

  public override Type ReturnedClass {
     get { return typeof(long[]); }
  }

  public override object FromStringValue(string xml) {
     string[] stringElements = xml.Split(';');
     long[] array = new long[stringElements.Length];

     for (int i = 0; i < stringElements.Length; i++) {
        array[i] = Convert.ToInt64(stringElements[i]);
     }

     return array;
  }
}
0 голосов
/ 27 апреля 2011

Ваш тип - Вложенная таблица. Вам нужен ассоциативный массив, который создается путем добавления предложения INDEX BY, как я уже показал в своем первом ответе.

...