Проблема с хранимой процедурой Oracle, возвращающей SYS_REFCURSOR и Entity Framework Model

У меня есть база данных Oracle (11.2 на стороне сервера с 12.1 клиентскими битами) с множеством хранимых процедур, которые возвращают тип объекта SYS_REFCURSOR.

Я попытался импортировать этот набор процедур с помощью мастера Добавить новую модель данных сущности ADO.NET в Visual Studio 2017 (15.6.3) и клиента Oracle Managed DataAccess (12.1). Но когда я получаю доступ к этим хранимым процедурам, я получаю исключение, такое как следующее:PLS-00306: wrong number or types of arguments in call to 'my_procedure'

Пример такой хранимой процедуры Oracle выглядит следующим образом:

create or replace PROCEDURE my_procedure (
       input               IN  VARCHAR2,
       cur_output OUT SYS_REFCURSOR
)
IS
BEGIN
    OPEN cur_output FOR
    SELECT    col1
    ,    col2
    ,    col3
    FROM my_table
    WHERE col1 = input;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            NULL;
        WHEN OTHERS THEN    
            RAISE;
END my_procedure;

Сгенерированная модель xml выглядит так:

<Function Name="my_procedure" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="myschema">
    <Parameter Name="input" Type="varchar2" Mode="In" />
</Function>

Сгенерированный код C# выглядит следующим образом:

public virtual int my_procedure(string input) {
    var inputParameter = input != null ?
        new ObjectParameter("input", input) :
        new ObjectParameter("input", typeof(string));

    return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("my_procedure", inputParameter);
}

Я немного поиграл с вызовом API Oracle DataAccess вручную, и работает следующий код:

OracleConnection conn = new OracleConnection(...);  
conn.Open();
using (OracleCommand cmd = new OracleCommand("my_procedure", conn)) {
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("input", OracleDbType.Varchar2).Value = "myinput";                
    cmd.Parameters.Add("cur_output", OracleDbType.RefCursor, null, ParameterDirection.Output);
    var dr = cmd.ExecuteReader();
    dr.Read();
    var col1id = dr.GetOrdinal("col1");
    var valuecol1 = SafeGetString(dr, col1id);
}
conn.Dispose();

В идеале я хотел бы иметь автоматизированный процесс для генерации правильного кода C# для доступа к хранимым процедурам. Какой самый практичный способ исправить это?

1 ответ

Вы определяете свою хранимую процедуру как my_procedure с двумя аргументами, input и cur_output. Когда вы вызываете эту процедуру в C#, вы также должны передать параметр FOR BOTH input и cur_output. Процедура не является функцией, в которой она возвращает значение. Процедура назначит вывод переменной, которую вы назначили в качестве параметра OUT, который в данном случае называется cur_output.

Другие вопросы по тегам