Функция C# OleDb Oracle и типы таблиц

я пытаюсь вызвать функцию Oracle, которая возвращает тип, инкапсулированный в таблице

Тип объекта

create or replace
type Z_TBL_STRUCTURE_CODE
AS OBJECT
(
    PROJ_ID varchar2(50 BYTE)
);

Таблица типов

create or replace
type Z_TABLE_STRUCTURE_CODE AS TABLE of Z_TBL_STRUCTURE_CODE;

Функция оракула

create or replace
FUNCTION Z_TESTE_IN_FUNC
(
    var_teste in varchar2
)
return Z_TABLE_STRUCTURE_CODE
AS
tab Z_TABLE_STRUCTURE_CODE;
BEGIN
  EXECUTE IMMEDIATE
    'SELECT 
    CAST(
    MULTISET(
      select count(*) into num from structure 
      where structure_code in ('|| var_teste ||')) as Z_TABLE_STRUCTURE_CODE)
    into tab
    from dual;';
  dbms_output.put_line(var_teste);
  return tab;
 END Z_TESTE_IN_FUNC;

ПРИМЕЧАНИЕ: ПОЖАЛУЙСТА, ИГНОРИРУЙТЕ НЕМЕДЛЕННОЕ ВЫПОЛНЕНИЕ, ЭТО ТОЛЬКО ДЛЯ ТЕСТА.

ПРИМЕЧАНИЕ 2: Я ЗНАЮ, ЧТО ЕСТЬ ВОЗМОЖНОСТЬ ИЗБЕЖАТЬ ТИПОВ (ИСПОЛЬЗУЯ КУРСОРЫ), НО Я ЕЩЕ НЕ СМОГ ПОНЯТЬ ТЕМУ, ПОЭТОМУ Я ПРОШУ ВАС ИГНОРИРОВАТЬ КУРСЫ ПРИ ОТВЕТЕ, ЕСЛИ ЭТО ЕДИНСТВЕННЫЙ ВАРИАНТ.

Код С#

public DataTable getTaskStartFinish()
{
    OleDbConnection con = null;
    OleDbDataReader reader = null;
    try{
        con = new OleDbConnection(ConfigurationManager.ConnectionStrings["OracleBD"].ConnectionString);

        OleDbCommand cmd = new OleDbCommand("", con);
        cmd.CommandText = "Z_TESTE_IN_FUNC";
        cmd.CommandType = CommandType.StoredProcedure;

        OleDbParameter retval = new OleDbParameter("retval", OleDbType.VarChar, 10);
        retval.Direction = ParameterDirection.ReturnValue;

        OleDbParameter inval = new OleDbParameter("inval", OleDbType.Variant, 50);
        inval.Direction = ParameterDirection.Input;
        inval.Value = "1";

        cmd.Parameters.Add(retval);
        cmd.Parameters.Add(inval);
        con.Open();

        reader = cmd.ExecuteReader();

        DataTable dt = new DataTable();
        dt.Load(reader);

        return dt;
    }
    catch(Exception ex)
    {
        throw new Exception("getTaskStartFinish error: " + ex.Message);
    }
    finally
    {
        if(con != null)
            con.Close();
        if(reader != null || !reader.IsClosed)
            reader.Close();
    }
}

Текущая ошибка, которую я получаю, следующая: ORA-06550: строка 1, столбец 13: PLS-00382: выражение имеет неправильный тип ORA-06550: строка 1, столбец 7: PL/SQL: оператор игнорируется

Я видел в сети подобные примеры, но все они использовали ExecuteScalar() или некоторый код для процедур или функций, возвращающих единичные значения, но не таблицы.


person FEST    schedule 10.04.2013    source источник


Ответы (1)


Хорошо, если вы хотите вернуть одно значение, мое предложение (отредактировано для нескольких строк):

        OleDbConnection conn = new OleDbConnection(ConfigurationManager.ConnectionStrings["OracleBD"].ConnectionString);
        OleDbCommand cmd = new OleDbCommand("Z_TESTE_IN_FUNC", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@procValueName", "myValue");
        OleDbDataAdapter da = new OleDbDataAdapter(cmd);
        DataTable dt = new DataTable();
        conn.Open();
        try
        {
            da.Fill(dt);
        }
        catch (Exception excp)
        {
            //Handle Exception
        }
        finally
        {
            conn.Close();
        }

Редактировать 2: попробуйте это для функции

OleDbConnection con = new OleDbConnection(cntStr);
con.Open();
OleDbCommand cmd = new OleDbCommand("F_TESTFUNC", con); 
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OleDbParameter("retVal", OleDbType.VarChar, 11,ParameterDirection.ReturnValue, true, 0, 0, "retVal", DataRowVersion.Current,null);
cmd.Parameters.Add("ID", strID);
cmd.ExecuteScalar();
con.Close();
person Xelom    schedule 11.04.2013
comment
Привет, Xelom, это было бы нормально, если бы я хотел одно значение да. но я делаю вид, что получаю несколько значений и несколько строк. У меня есть способ сделать это, но он небезопасен и подвержен внедрению sql (используя базовый способ установки моего sql и переменных в строке и отправки строки в cmd.CommandText). Поскольку я хочу избежать этого, я попробовал способ, который я показал, но он не работает. - person FEST; 11.04.2013
comment
Редактирование моего ответа для нескольких строк, затем - person Xelom; 11.04.2013
comment
Привет Кселом. Итак, я попробовал ваш код и получил следующую ошибку: {System.Data.OleDb.OleDbException: ORA-06550: строка 1, столбец 7: PLS-00221: «Z_TESTE_IN_FUNC» не является процедурой или не определена ORA-06550: строка 1, столбец 7: PL/SQL: заявление игнорируется. Нужно ли мне делать что-то еще, потому что я хочу выполнить функцию? могу ли я использовать любое имя в addwithParameter? - person FEST; 11.04.2013