Ошибка типов данных Oracle ODP при вызове хранимых процедур

Я конвертирую устаревшее приложение из устаревшего поставщика данных Microsoft .Net для Oracle (Sql.Data.OracleClient.dll) в собственный поставщик Oracle .Net ODP (OracleManagerDataAccess.dll) с использованием последней версии пакета Nuget. Сервер базы данных - Oracle 11g

Проблема, которую я не понимаю, заключается в том, что когда приложение вызывает хранимую процедуру с использованием поставщика Microsoft, это нормально, но когда я переключаюсь на использование Oracle ODP, я получаю следующую ошибку при вызове хранимой процедуры:

ORA-06502: PL/SQL: numeric or value error: character to number conversion error\nORA-06512: at line 1

Я преобразовал код в очень простое консольное приложение, которое демонстрирует ту же проблему (см. Ниже), но я не могу понять, что мне нужно делать по-другому с Oracle ODP. Выполнение «нормального» sql, созданного из приложения, кажется нормальным.

Вызывающий объект IDbCommand передает 4 параметра, два из которых являются строковыми, а два - целыми. Заголовок хранимой процедуры

PROCEDURE  CreateSampleResults(varSampleCode SampleResults.SampleCode%TYPE, varTestPosition SampleResults.TestPosition%TYPE, varTestCode TestComponents.TestCode%TYPE, varTestVersion TestComponents.AuditNumber%TYPE) 

Ничего в базе данных не изменилось, только поставщик данных в приложении .Net. Коллекции параметров команды идентичны независимо от того, используются ли поставщики данных Microsoft или Oracle.

Вот простое приложение, демонстрирующее проблему:

using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Generic;
using System.Data;
//using System.Data.OracleClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace oracleconnect
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                InitializeDBConnection();
                CreateSampleResults("S0106", "a", 2, 1);
            }
            finally
            {
                if (_con.State==System.Data.ConnectionState.Open)
                _con.Close();
            }
        }

        static private OracleConnection _con;
        private const string connectionString =
        "Data Source = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = oracledbserver2)(PORT = 1521))(CONNECT_DATA = (SERVICE_NAME = orcdb10g))); User ID = myDatabasenameHere; Password=myPasswordhere";

        private static void InitializeDBConnection()
        {
            _con = new OracleConnection();
            _con.ConnectionString = connectionString;
            _con.Open();
        }

        public static IDbCommand CreateCommand(IDbConnection cn, string procedureName)
        {

            IDbCommand command = cn.CreateCommand();
            command.CommandTimeout = 30;
            command.Connection = cn;
            command.CommandType = System.Data.CommandType.StoredProcedure;
            command.CommandText = procedureName;

            return command;
        }

        public static void CreateSampleResults(string sampleCode, string testCode, short testVersion, short testPosition)
        {
            {
                using (IDbCommand cmd = CreateCommand(_con, "CreateSampleResults"))
                {
                    SetParameter("Oracle", cmd, "SampleCode", sampleCode);
                    SetParameter("Oracle", cmd, "TestCode", testCode);
                    SetParameter("Oracle", cmd, "TestVersion", testVersion);
                    SetParameter("Oracle", cmd, "TestPosition", testPosition);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        public static void SetParameter(string databaseType, IDbCommand command, string name, object value)
        {
            System.Data.IDataParameter commandParameter = command.CreateParameter();
            commandParameter.ParameterName = string.Format("var{0}", name);
            commandParameter.Value = value;
            var x = commandParameter.DbType;
            command.Parameters.Add(commandParameter);
        }

        public enum DatabaseType { DBError, OLEDB, SQLServer, Oracle, /*SQLite,*/ Odbc };

    }
}

Я подозреваю, что проблема может быть связана с использованием предполагаемых типов данных в хранимой процедуре (т.е. имя таблицы% TYPE), но это предположение. Кто-нибудь знает, что нужно сделать, чтобы вызовы хранимых процедур работали с Oracle ODP?

TIA


person haughtonomous    schedule 19.12.2016    source источник
comment
Не уверен на 100%, но есть некоторые воспоминания о том, что ODP.NET по умолчанию связывает параметры по положению, а не по имени. Вы можете попробовать изменить порядок вызовов SetParameter, чтобы они соответствовали параметрам SP.   -  person Ivan Stoev    schedule 19.12.2016
comment
Ура! Вот и все, на гвоздь. Спасибо, Oracle молодец за то, что он такой тупой. если вы что-то заменяете, по крайней мере, заставьте его работать так же. :-(   -  person haughtonomous    schedule 19.12.2016


Ответы (1)


Вам следует добавить в вашу commandParameter базу данных DbType. Ошибка связана с преобразованием типа в oracle, когда вызывается последняя команда. Эта ошибка вызвана преобразованием commandParameter.Value в окончательный тип базы данных.

https://msdn.microsoft.com/en-us/library/system.data.idataparameter.dbtype(v=vs.110).aspx

person Bernd Ott    schedule 19.12.2016