«ORA-03115: неподдерживаемый сетевой тип данных или представление» при попытке заполнить DataSet - PullRequest
1 голос
/ 28 марта 2019

Я пытаюсь заполнить объект DataSet объектом OracleCommand, я только начал использовать Oracle, я использую SQL Server всю свою жизнь.В своем проекте консоли NET я добавил пакет NuGet Oracle.ManagedDataAccess и изменил объекты Sql на Oracle.Как: SqlConnection для OracleConnection.В SQL Server он работает отлично, но в Oracle он дает мне эту ошибку, я не совсем понимаю, что это значит.

Я изменил SqlConnection на OracleConnection и SqlCommand на OracleCommand

также

command.Parameters.AddWithValue("@" + parameters[i], values[i] ?? DBNull.Value);

до

command.Parameters.Add(parameters[i], values[i] ?? DBNull.Value);
command.Parameters[i].Value = values[i];

Поскольку AddWithValue не существует на OracleCommand

Это метод, который получает данныеиз базы данных.

        private void GetData(string storedProcedure, IReadOnlyList<string> parameters, IReadOnlyList<object> values)
        {
            using (var connection = new OracleConnection(_connectionString))
            {
                using (
                    var command = new OracleCommand(storedProcedure, connection)
                    {
                        CommandType = CommandType.StoredProcedure
                    })
                {
                    if (parameters != null)
                        for (var i = 0; i < parameters.Count; i++)
                        {
                            command.Parameters.Add(parameters[i], values[i] ?? DBNull.Value);
                        }
                    var ds = new DataSet();
                    connection.Open();
                    new OracleDataAdapter(command).Fill(ds);
                    _data = ds.Tables;
                    connection.Close();
                }
            }
        }

Это параметры, которые я использую.

            var db = new Connector.Provider("AIA.GET_DATA",
                new[]{
                    "Test1",
                    "Test2",
                    "Test3",
                    "Test4"},
                new object[]{
                    1,
                    2,
                    3,
                    null});

И это хранимая процедура.

  PROCEDURE GET_DATA(
    Test1           in NUMBER,
    Test2           in NUMBER,
    Test3           in NUMBER,
    Test4           in NUMBER,
    TestOut        out SYS_REFCURSOR
    );

В конструкторе поставщикаон получает строку подключения и использует метод GetData.

Сбой:

new OracleDataAdapter(command).Fill(ds);

Oracle.ManagedDataAccess.Client.OracleException: 'ORA-03115: неподдерживаемый тип сетевых данных или представление'

Опять же, это прекрасно работает на SQL Server.

Любая помощь приветствуется, по крайней мере, что означает это сообщение об ошибке.


РЕДАКТИРОВАТЬ:

Спасибо, Люк Вудворд, это было очень полезно.Так что была проблема с параметром OUT, а также с типом параметров, которые я отправлял. Так что это решает проблему.

В любом случае, я остановился на этом новом методе.Который работает нормально, за исключением нуля.

    private void GetData(string storedProcedure, IReadOnlyList<string> parameters, IReadOnlyList<object> values, IReadOnlyList<string> cursors)
    {
        using (var connection = new OracleConnection(_connectionString))
        {
            using (
                var command = new OracleCommand(storedProcedure, connection)
                {
                    CommandType = CommandType.StoredProcedure
                })
            {
                if (parameters != null)
                    for (var i = 0; i < parameters.Count; i++)
                    {
                        var parameter = new OracleParameter();
                        parameter.ParameterName = parameters[i];
                        if (values[i] is Enum)
                            parameter.Value = (int)values[i];
                        else
                            parameter.Value = values[i];

                        if (cursors != null && cursors.Contains(parameter.ParameterName))
                        {
                            parameter.Direction = ParameterDirection.Output;
                            parameter.OracleDbType = OracleDbType.RefCursor;
                        }
                        else
                        {
                            parameter.OracleDbType = GetOracleType(values[i]);
                        }
                        command.Parameters.Add(parameter);
                    }

                var ds = new DataSet();
                connection.Open();
                new OracleDataAdapter(command).Fill(ds);
                _data = ds.Tables;
                connection.Close();
            }
        }
    }

В Sql я мог бы использовать DBNull.Value, но в Oracle мне нужно определить OracleDbType, что раздражает, так как этот метод работает для любого объекта, а незаботясь о типе, теперь я все еще не знаю, как это исправить, чтобы он работал с любым объектом в Oracle. Но это можно считать оффтопом, этот вопрос можно пометить как ответивший.

1 Ответ

1 голос
/ 29 марта 2019

Вам необходимо добавить OracleParameter для параметра OUT TestOut, но вы этого не делаете.

Добавьте эти строки после других строк, которые устанавливают параметры:

    var outParam = new OracleParameter("TestOut", OracleDbType.RefCursor, ParameterDirection.Output);
    command.Parameters.Add(outParam);

Затем вам нужно будет выполнить команду отдельно, а не передавать команду на OracleDataAdapter. Сделайте это, добавив строку

    command.ExecuteNonQuery();

сразу после двух, которые добавляют outParam.

Наконец, заполните набор данных из курсора ref параметром OUT, заменив строку

    new OracleDataAdapter(command).Fill(ds);

с

    new OracleDataAdapter().Fill(ds, (OracleRefCursor)outParam.Value);

Кстати, я получил другую ошибку при запуске вашего кода. Я получил ошибку PLS-00306: wrong number or types of arguments in call to 'GET_DATA'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...