2010-11-22 30 views
3

J'ai créé un petit outil de requête pour Oracle avec fonction d'exportation CSV avec un OracleDataAdapter pour remplir un ensemble de données affiché dans un DataGrid (WinForms). Au début, j'ai utilisé les types .NET (DateTime, decimal, string, ...) mais j'ai eu des exceptions de débordement dans certains cas en raison d'une plus grande précision dans Oracle (NUMBER(30,10)). Par conséquent, j'ai dû définir la propriété ReturnProviderSpecificTypes = true dans OracleDataAdapter afin qu'il utilise maintenant les types OracleClient (OracleNumber, OracleBoolean, OracleString, ...). Le problème est que tout est toujours localisé (à l'écran et pendant la sortie CSV) dans les formats en-US lorsque je suis dans la région nl-BE (nous utilisons la virgule comme séparateur décimal et point comme séparateur de milliers). Le séparateur de colonnes dans CSV est un point-virgule btw, donc il n'y a pas d'interférence avec la virgule dans les nombres décimaux.Comment formater OracleNumber de manière générique

Y a-t-il un moyen de remplacer la méthode ToString d'une manière pour ces types? Une sorte d'injection d'un moteur de formatage?

Merci

Répondre

1

On dirait qu'il n'y a pas de bonne façon générique de le faire. Pour la sortie CSV, j'ai trouvé une solution de contournement mais pas pour la sortie à l'écran.

Pendant la sortie, je dois tester chaque valeur pour le type OracleNumber (je dois quand même tester INullable) et le lancer en conséquence. Ensuite, il y a deux options:

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

ou

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

Pour la sortie sur l'écran que nous pourrions utiliser une technique similaire et charger une nouvelle DataTable en mémoire de celui rempli par le OracleDataAdapter mais avec .NET Les types CLR, mais puisque les résultats peuvent être très gros, cela pourrait être un truc dangereusement lourd à faire, donc nous allons juste vivre avec la notation anglaise là-bas ...

0
SQL>select to_char(1000001/3, '999G999G990D999999', 'NLS_NUMERIC_CHARACTERS = '',.''') 
from dual; 

33.3333,666667

AJOUTEE:

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

Voir http://cs.felk.cvut.cz/10gr2/win.102/b14307/OracleGlobalizationClass.htm#i1010070 pour les paramètres possibles

+0

C'est un outil de requête. Les utilisateurs peuvent entrer n'importe quelle requête. Je n'ai aucun contrôle sur la requête du tout ... – Koen

+0

De la FAQ: Surtout, soyez honnête. Si vous voyez _misinformation_, votez en bas. –

+0

La classe OracleGlobalization fait partie du fournisseur de données Oracle Data Access (que j'ai préféré ne pas utiliser). Cela ne va pas aider de toute façon car cela ferait la même chose que d'envoyer la commande "alter session set NLS_NUMERIC_CHARACTERS = '," "mais j'ai déjà testé ça ... – Koen

1

Vous pouvez utiliser ALTER SESSION SET NLS_.... Regardez: http://download.oracle.com/docs/cd/B28359_01/olap.111/b28126/dml_options072.htm

Il est par exemple de la façon dont cela fonctionne avec le point décimal ad points et l'espace comme séparateur de milliers (note également paramètre datetime):

alter session set NLS_NUMERIC_CHARACTERS='. ' 
alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS' 
+0

Fonctionne dans Oracle SQL développeur mais pas à partir du code. J'ai essayé d'envoyer ceci en tant que commande distincte avant la déclaration réelle mais cela n'affecte rien. Les données sont encore enveloppées dans ces types spécifiques d'Oracle et leurs méthodes ToString font exactement la même chose ... – Koen

+0

Pour moi cela fonctionne avec ODBC (à la fois de Delphi et de Jython via le pont JDBC-ODBC). Quelle technologie utilisez-vous pour vous connecter à Oracle db? –

+0

Testé avec le client JDBC natif et ne fonctionne pas! –