Как форматировать OracleNumber в общем - PullRequest
3 голосов
/ 22 ноября 2010

Я создал небольшой инструмент запросов для Oracle с функцией экспорта CSV с помощью OracleDataAdapter для заполнения набора данных, который отображается в DataGrid (WinForms). Сначала я использовал типы .NET (DateTime, decimal, string, ...), но в некоторых случаях я получал исключения переполнения из-за большей точности в Oracle (NUMBER(30,10)). Поэтому мне пришлось установить свойство ReturnProviderSpecificTypes = true в OracleDataAdapter, чтобы теперь вместо него использовались типы OracleClient (OracleNumber, OracleBoolean, OracleString, ...).

Проблема в том, что все всегда локализовано (на экране и во время вывода CSV) в форматы en-US, пока я нахожусь в регионе nl-BE (мы используем запятую как десятичный разделитель и точку как разделитель тысяч). Разделитель столбцов в CSV, между прочим, является точкой с запятой, поэтому нет запятой в десятичных числах.

Так есть ли способ переопределить метод ToString способом для этих типов? Какая-то инъекция механизма форматирования?

Спасибо

Ответы [ 3 ]

1 голос
/ 22 ноября 2010

Вы можете использовать ALTER SESSION SET NLS_....Смотрите: http://download.oracle.com/docs/cd/B28359_01/olap.111/b28126/dml_options072.htm

Есть пример того, как это работает с десятичной точкой и пробелом в качестве разделителя тысяч (также обратите внимание на настройку даты и времени):

alter session set NLS_NUMERIC_CHARACTERS='. '
alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS'
1 голос
/ 23 ноября 2010

Похоже, что нет хорошего общего способа сделать это.Для вывода CSV я нашел обходной путь, но не для вывода на экран.

Во время вывода я должен проверить каждое значение для типа OracleNumber (в любом случае я должен проверить на INullable) и привести его соответственно.Тогда есть два варианта:

// Replace: not clean and could be a heavy operation
writer.Write(myOracleNumber.ToString().Replace('.', ','));

или

// Returns decimal but result is not exact (which is acceptable in my case)
writer.Write(OracleNumber.Round(myOracleNumber, 10).Value);

Для вывода на экран мы могли бы использовать аналогичную технику и загрузить новый DataTable в память из того, который был заполнен OracleDataAdapter, нозатем с типами .NET CLR, но поскольку наборы результатов могут быть очень большими, это может быть опасно тяжелым трюком, поэтому мы просто будем жить там с английской нотацией ...

0 голосов
/ 22 ноября 2010
SQL>select to_char(1000001/3, '999G999G990D999999', 'NLS_NUMERIC_CHARACTERS = '',.''')
from dual;

33.3333,666667

ДОБАВЛЕНО:

private si As OracleGlobalization; 
si.DateFormat = "YYYY-MM-DD";
conn.SetSessionInfo(si);

См. http://cs.felk.cvut.cz/10gr2/win.102/b14307/OracleGlobalizationClass.htm#i1010070 для возможных параметров

...