DataReader возвращает неверный тип данных .net для столбца с плавающей точкой таблицы базы данных

#c# #oracle #ado.net #oracle-sqldeveloper #oracle.manageddataaccess

#c# #Oracle #ado.net #oracle-sqldeveloper #oracle.manageddataaccess

Вопрос:

У меня есть 1 таблица в Oracle SQL Developer, которая содержит 1 column as Float . Data reader должно вернуться Decimal for oracle float datatype в соответствии с приведенной здесь таблицей :https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/oracle-data-type-mappings

Но проблема в том, что datareader возвращает double as datatype для Float Column , как показано ниже : введите описание изображения здесь

Но проблема в том, что datareader возвращает double как тип данных для NREAL as Float и NFLOAT1 as float и, что удивительно, datareader возвращает Decimal for both the column , как показано ниже :

введите описание изображения здесь

Код :

 static void Test()
        {
            using (OracleConnection connection = new OracleConnection("connection string")
            {
                connection.Open();
                using (OracleCommand command = connection.CreateCommand())
                {
                    command.CommandText = "select id , NFLOAT from Numeric_Table";
                    using (OracleDataReader reader = command.ExecuteReader())
                    {
                        for (int i = 0; i < reader.FieldCount; i  )
                        {
                            var columnName = reader.GetName(i);
                            var dotNetType = reader.GetFieldType(i);
                            var sqlType = reader.GetDataTypeName(i);
                        }
                    }
                }
            }
        }
  

Я использую : Oracle.Управляемый доступ к данным.Клиент

Это ошибка внутри Oracle.ManagedDataAccess.Client library или я делаю что-то не так?

Обновление : Основываясь на комментариях, я хочу кое-что упомянуть :

Хотя у меня может быть ссылка на другую исходную документацию, не применимую к библиотеке Oracle, которую я использую, bt, тем не менее, я получаю десятичный тип данных для моих других 2 столбцов, т. Е. NREAL и NFLOAT1, так почему же это поведение не согласуется?

Комментарии:

1. System.Data.OracleClient <> Oracle.ManagedDataAccess.Client поэтому у него может быть другая привязка

2. Если вы используете Oracle.ManagedDataAccess , то вы просматриваете неправильную документацию, потому что та, на которую вы ссылались, предназначена для System.Data.OracleClient . Попробуйте docs.oracle.com/database/121/ODPNT/toc.htm

3. @Selvin Но дело в том, что для других столбцов, т. Е. NREAL и NFLOAT1, я получаю десятичный тип данных. Что насчет этого?

4. @Dirk Но дело в том, что для других столбцов, т. Е. NREAL и NFLOAT1, я получаю десятичный тип данных. Что насчет этого?

Ответ №1:

FLOAT Тип данных — это не вся картина здесь. Разработчик SQL не показывает вам, что NFLOAT имеет точность менее 50, в то время как NREAL и NFLOAT1 имеют точность 50 или выше. Оставлено неуказанным при создании, точность по умолчанию 126, что является максимально возможной точностью для типа данных с плавающей запятой.

Простой тестовый запрос продемонстрирует разницу:

 SELECT CAST(0 AS FLOAT(49)), CAST(0 AS FLOAT(50)) FROM DUAL
  

Первый столбец будет возвращен как System.Double . Второй будет возвращен как System.Decimal .

В SQL Developer щелкните правой кнопкой мыши по таблице и выберите «Редактировать …» Это диалоговое окно действительно показывает определенную точность для столбца.

Если вы хотите, чтобы он NFLOAT возвращался как System.Decimal , увеличьте точность как минимум до 50.


В последнее время я просматривал документацию и запускал свои собственные тесты. Это любимый проект, и я не использую Oracle регулярно, поэтому было много проб и ошибок. DUMP Функция оказалась весьма полезной при определении того, правильный ли у меня тип данных в выражении, прежде чем посмотреть, что с ним делает ODP .NET.

Рассмотрим другой пример того, как ODP .NET возвращает разные типы данных в зависимости от точности NUMBER(p,0) .

 Type     Min p    Max p
---------------------------
Int16    1        4
Int32    5        9
Int64    10       18
Decimal  19       38
  

Я надеялся, что Byte or SByte будет возвращено, когда p будет 1 или 2, но это не сработало.

Комментарии:

1. Проголосовал за ваши добрые усилия, направленные на то, чтобы помочь мне, и за ваше драгоценное время и ответ. Согласно таблице, показанной здесь ( docs.oracle.com/cd/B19306_01/win.102/b14306/appendixa.htm ) кажется, что float может возвращать что угодно, что так странно

2. Нет, эта таблица не говорит о том, что это типы, которые могут быть возвращены, а скорее о том, что диапазоны этих типов .NET могут быть представлены связанным типом Oracle, и наоборот во второй таблице. ODP.NET вернет только Double или Decimal для FLOAT . Я протестировал FLOAT с точностью 1, 49, 50, 126 и несколькими другими вокруг этих пределов, чтобы подтвердить это. Для любого другого типа потребуется приведение или преобразование.

3. Все в порядке. Большое вам спасибо. Ваш ответ и комментарий действительно полезны 🙂