2009-06-06 30 views
11

Con estaC# Oracle procedimiento almacenado parámetro de orden

PROCEDURE "ADD_BOOKMARK_GROUP" (
    "NAME" IN VARCHAR2, 
    "BOOKMARK_GROUP_ID" IN NUMBER, 
    "STAFF_ID" IN VARCHAR2, 
    "MAX_NO" IN INT, 
    "NUMFOUND" OUT INT, 
    "NEW_ID" OUT NUMBER) IS 

BEGIN 

NEW_ID := -1; 

SELECT COUNT(*) INTO NUMFOUND FROM BOOKMARK_GROUP_TABLE WHERE STAFF_ID = STAFF_ID; 

IF NUMFOUND < MAX_NO THEN 
    INSERT INTO BOOKMARK_GROUP_TABLE (NAME, BOOKMARK_GROUP_ID, STAFF_ID) VALUES(NAME, BOOKMARK_GROUP_ID, STAFF_ID); 
    SELECT BGT_SEQUENCE.currval INTO NEW_ID FROM dual; 
END IF; 
END; 

Me parece interesante que si no añado parámetros en el orden en que se definen en, por ejemplo,

OracleCommand cmd = new OracleCommand("ADD_BOOKMARK_GROUP", conn); 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Parameters.Add(new OracleParameter("NAME", name)); 
... 
cmd.Parameters.Add(new OracleParameter("NEW_ID", OracleDbType.Decimal)).Direction = ParameterDirection.Output; 
cmd.Parameters.Add(new OracleParameter("NUMFOUND", OracleDbType.Int32)).Direction = ParameterDirection.Output; 

en lugar de

OracleCommand cmd = new OracleCommand("ADD_BOOKMARK_GROUP", conn); 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Parameters.Add(new OracleParameter("NAME", name)); 
... 
cmd.Parameters.Add(new OracleParameter("NUMFOUND", OracleDbType.Int32)).Direction = ParameterDirection.Output; 
cmd.Parameters.Add(new OracleParameter("NEW_ID", OracleDbType.Decimal)).Direction = ParameterDirection.Output; 

Los valores devueltos por

cmd.Parameters["NEW_ID"].Value.ToString() 

y

cmd.Parameters["NUMFOUND"].Value.ToString() 

swapeada, a pesar de ejecutar el procedimiento a través del Explorador de servidores VS2008 devuelve los datos correctos .

¿Por qué es esto?

Respuesta

10

No soy un buff de Oracle, por lo que no puedo verificarlo, pero suena como si se pasara por posición (en lugar de pasar por su nombre). La moral de equivelent:

EXEC SomeProc 'Foo', 'Bar' 

en lugar de:

EXEC SomeProc @arg1='Foo', @arg2='Bar' 

Esto no es enormemente raro - por años (en los días COM) una gran parte de mi código tenía que trabajar con un by-pass -posición de controlador ADODB.

En este caso, el nombre que proporcione solo como clave local para buscar el valor de la colección de colecciones. Puede verificar fácilmente inventando un nombre:

cmd.Parameters.Add(new OracleParameter("BANANA", ... 
cmd.Parameters.Add(new OracleParameter("GUITAR", ... 
... 
cmd.Parameters["BANANA"].Value.ToString() 
cmd.Parameters["GUITAR"].Value.ToString() 

Si lo anterior se ejecuta sin error, está pasando por posición. Y es que son pasados ​​por posición ... luego simplemente agréguelos en el orden correcto ;-p Y nunca agregue nuevos parámetros, excepto al final ...

+0

por lo que están siendo pasado por la posición, aunque el paso por nombre sería mucho más útil. –

24

probablemente haya establecido el parámetro BindByName en el objeto OracleCommand. Esto funciona para las consultas SQL con parámetros rectas, no lo he probado con los procedimientos almacenados, pero sería lógico ...

cmd.BindByName = true; 
+5

Esta es la verdadera respuesta. Debe ser aceptado –

+0

Estoy de acuerdo @JohnGietzen, esta debería ser la respuesta aceptada – Ergec

+0

Esto me salvó de ser más calvo. Procedente de un fondo de SQL Server que hace esto de forma predeterminada, estaba tratando de entender por qué una consulta en línea con parámetros no funcionaba. ¡Gracias! – Caverman

Cuestiones relacionadas