C# OUTPUT Parameters & return @@identity

El día de hoy me agarró una manifestación en Reforma. Ya sé que mis cuates de CrossHorizons nunca me creen cuando les digo que me agarró una manifestación, pero se los juro… ¡tengo mala suerte para eso!

Pero bueno, fué un éxito la presentación de LuzVerde solo que el sitio andaba muy lento … o su red, no sé. Mañana nos espera un día de infraestructura a Andrecito y a mi en Laboratorios, a ver que tal nos va con Windows 2003 Server y las demás vainas que se encuentran alrededor de esto.

Tengo unas ganas de programar, pero no he tenido tiempo por tantas reuniones. Tengo que pasarle las specs de construcción Willy para Elsa, creo que me voy a poner a trabajar en eso, y ya postearé algo de código en C#.

Ah, por cierto… hoy me hicieron una pregunta uno de mis alumnos de Softtek:

Q: ¿Cómo obtener el valor de un parámetro Output de un stored-procedure en C#?
R: Pos así:

Digamos que tenemos una tabla que se llama Estados. Esta tabla contiene dos campos, un campo Identity que se llama idEstado y un campo varchar que se llama Nombre. Nosotros utilizamos un sp de inserción que se llama spI_Estados, el cual contiene el siguiente código:

1 ALTER PROCEDURE intellektdb.spI_Estados
2
3 @nombre varchar(30)
4
5 AS
6
7 INSERT INTO
8 Estados([nombre])
9 VALUES
10 (@nombre)

Si te fijas, esta insertando directamente a la tabla; y como tenemos un campo identity automáticamente SQL Server se encargará de manejar el consecutivo. Esto esta perfecto y funciona bien, si lo que queremos es solamente insertar y no nos importa saber el valor de la columna idEstado, una vez que se haya insertado el registro. Pero ¿que creen? que si nos importa, por que queremos almacenar ese valor dentro de una propiedad de nuestro objeto de datos.

Entonces lo que tendríamos que hacer dentro del sp es lo siguiente:

1 ALTER PROCEDURE intellektdb.spI_Estados
2
3 @nombre varchar(30),
4 @idEstado smallint OUTPUT
5
6 AS
7
8 BEGIN TRAN
9 INSERT INTO
10 Estados([nombre])
11 VALUES
12 (@nombre)
13
14 SELECT @idEstado = @@identity
15 COMMIT TRAN

Hicimos las siguientes adiciones:

  1. Añadimos una nueva variable idEstado de tipo smallint y de salida OUTPUT (línea 4) que va almacenar el valor de retorno del campo de la inserción.
  2. Hicimos que nuestras sentencias SQL jalen dentro de una transacción (linea 8 y 15)
  3. Asignamos el valor de salida idEstado a una variable interna de SQL Server que se llama @@identity.

Ahora, necesitamos meter el código que mande a llamar nuestro sp con los parámetros adecuados. Lo que tenemos que hacer es lo siguiente:

1 public bool Insert2(string nombre)
2 {
3 SqlConnection cn = new SqlConnection(«datasource=localhost;initial catalog=elsa_db;integrated security=true;»);
4 SqlCommand cmd = new SqlCommand(«spI_Estados», cn);
5 cmd.Parameters.Add(new SqlParameter(«@nombre», SqlDbType.VarChar, 30, ParameterDirection.Input));
6 cmd.Parameters.Add(new SqlParameter(«@idEstado», SqlDbType.SmallInt, 4, ParameterDirection.Output));
7
8 int _rows = cmd.ExecuteNonQuery();
9
10 //este es el valor actual de retorno del insert
11 int _idEstado = cmd.Parameters[«@idEstado»];
12 }

Vamos a analizar el código:

  1. Generamos una nueva conexion a la base de datos en base a nuestro ConnectionString. (línea 3)
  2. Creamos un SqlCommand que será el que ejecute el sp y tenga la colección de parametros (línea 4)
  3. Añadimos los parámetros al SqlCommand. Aquí asegurense siempre que los nombres de los parámetros sean idénticos a los que estan en el sp (incluyan la arroba @) para que no muestre ningún error. La diferencia entre el primer parámetro y el segundo; es que en el segundo, su dirección es de Salida (ParameterDirection.Output) (línea 5 y 6)
  4. Ejecutamos el query (linea 8)
  5. Obtenemos el valor regresado por la inserción en una variable que se llama _idEstado de la lista de parámetros de nuestro SqlCommand (cmd.Parameters[«@idEstado»]) (linea 11)

¡Voila! Ya logramos hacer un sp que tenga parámetros de salida y los llamamos desde C# para obtener el valor de retorno. Como pueden ver es muy sencillo el código, y muy fácil su implementación, solo hay que tomarlo en cuenta desde el inicio de la construcción de nuestros objetos de datos.

Cheers!


Comentarios

Deja una respuesta