27 votes

Requêtes paramétrées C # pour Oracle - bogue sérieux et dangereux!

C'est une absolue hurleurs. Je ne peux pas en croire mes propres yeux, et je ne peut pas croire à personne avant moi aurait découvert si c'était un véritable bug en C#, donc je vais mettre pour le reste de la communauté des développeurs à me dire ce que je fais de mal. Je suis sûr que cette question va impliquer de moi en disant "DOH!" et de claquer ma tête, très difficile avec la paume de ma main - mais voilà, de toute façon...

Pour des raisons de test, j'ai créé un tableau Test_1, avec un script comme suit:

CREATE TABLE TEST_1 (
  COLUMN1 NUMBER(12) NOT NULL,
  COLUMN2 VARCHAR2(20),
  COLUMN3 NUMBER(12))
TABLESPACE USERS
STORAGE (
  INITIAL 64K
  MAXEXTENTS UNLIMITED
)
LOGGING;

Maintenant j'exécute le code suivant:

var conn = new OracleConnection("connectionblahblah");
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = 
  "insert into Test_1(Column1, Column2, Column3) " +
  "values(:Column1, :Column2, :Column3)";
var p = cmd.Parameters;
p.Add("Column1", 1);
p.Add("Column3", null);
p.Add("Column2", "record 1");
cmd.ExecuteNonQuery();

Whoa! J'obtiens une erreur ORA-01722 erreur "numéro non valide"! Quel est le problème, si? Column1 est numérique, et a une valeur de 1, c'est très bien; Column2 est une chaîne de caractères, et Column3 est nullable de la colonne, de manière à ne pas causer d'ennuis...

Maintenant, asseyez-vous pour celui-ci... le problème ici est que, Column3 et Column2 sont transposées dans l'ordre dans lequel ils sont ajoutés à l' OracleParameterCollection. Basculer entre eux à travers, et hop! Il fonctionne!

Ceci, bien sûr, qui m'amène à la prochaine évident expérience... nous allons changer ce bloc de code pour ajouter des paramètres comme ceci:

p.Add("Foo", 1);
p.Add("Bar", "record 1");
p.Add("hahahahahahaha", null);

Vous pensez que ça va marcher? Eh bien, devinez quoi - il n'!

Je suis assis ici absolument stupéfait. Je ne peux pas croire ce que je vois, et de même, je ne crois pas que personne avant moi a découvert ce problème (sauf que je ne sais pas comment utiliser Google correctement).

Ce n'est pas seulement une nuisance - il est vraiment dangereux. Ce qui se serait passé si j'avais transposé deux colonnes du même type de données? Je n'aurais pas même eu une erreur - j'ai simplement inséré les données erronées dans le mauvais colonnes, et pas le plus sage.

Quelqu'un a une idée pour une solution de contournement - autre que juste en faisant attention de ne pas ajouter des paramètres dans le mauvais ordre?

36voto

Pratik Points 5401

Ce n'est pas un bogue, mais il est explicitement mentionné dans la documentation Oracle ODP.Net. Dans une classe OracleCommand, les paramètres sont liés par position par défaut. Si vous souhaitez lier par nom, définissez la propriété cmd.BindByName = true; explicite.

Référence à la documentation Oracle. http://download.oracle.com/docs/cd/E11882_01/win.112/e12249/OracleCommandClass.htm#i997666

4voto

OMG Ponies Points 144785

C'est qu'une faute de frappe que vous avez colonne3 être ajouté avant colonne2?

Parce que le côlon syntaxe signifie une liaison variable--nom n'a pas d'importance pour LIER les variables en PLSQL, ils sont remplis dans l'ordre de présentation. Ce qui voudrait dire que vous seriez tenté de mettre colonne2 valeur "dossier 1", ce qui expliquerait le nombre non valide erreur...

Actuellement vous avez:

p.Add("Column1", 1);
p.Add("Column3", null);
p.Add("Column2", "record 1");

...voir si cette modification corrige votre problème:

p.Add("Column1", 1);
p.Add("Column2", "record 1");
p.Add("Column3", null);

Obtenir les Paramètres Nommés pour Travailler?

Je dois en remettre à quelqu'un avec plus de C# expérience pour expliquer comment obtenir les paramètres nommés de travail. Mais je suis content que nous avons confirmé que le colon semble être interpréter comme un Oracle LIER des variables.

0voto

Luke Points 1
 p.Add(":Column1", 1);
p.Add(":Column2", "record 1");
p.Add(":Column3", null);
 

// REMARQUE: j'ai ajouté: aux noms de paramètres à reconnaître par le client de données Oracle

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X