Usar parámetros de salida de procedimiento almacenado en C #

Tengo un problema al devolver un parámetro de salida de un procedimiento almacenado en el servidor Sql a una variable C #. He leído las otras publicaciones relacionadas con esto, no solo aquí, sino en otros sitios, y no puedo hacer que funcione. Esto es lo que tengo actualmente. Actualmente estoy tratando de imprimir el valor que vuelve. El siguiente código devuelve un valor nulo. Lo que bash devolver es la clave principal. He intentado usar @@IDENTITY y SCOPE_INDENTITY() (es decir, SET @NewId = SCOPE_IDENTITY() ).

Procedimiento almacenado:

 CREATE PROCEDURE usp_InsertContract @ContractNumber varchar(7), @NewId int OUTPUT AS BEGIN INSERT into [dbo].[Contracts] (ContractNumber) VALUES (@ContractNumber) Select @NewId = Id From [dbo].[Contracts] where ContractNumber = @ContractNumber END 

Abriendo la base de datos:

 pvConnectionString = "Server = Desktop-PC\\SQLEXPRESS; Database = PVDatabase; User ID = sa; PASSWORD = *******; Trusted_Connection = True;"; try { pvConnection = new SqlConnection(pvConnectionString); pvConnection.Open(); } catch (Exception e) { databaseError = true; } 

Ejecutando el comando:

 pvCommand = new SqlCommand("usp_InsertContract", pvConnection); pvCommand.Transaction = pvTransaction; pvCommand.CommandType = CommandType.StoredProcedure; pvCommand.Parameters.Clear(); pvCommand.Parameters.Add(new SqlParameter("@ContractNumber", contractNumber)); SqlParameter pvNewId = new SqlParameter(); pvNewId.ParameterName = "@NewId"; pvNewId.DbType = DbType.Int32; pvNewId.Direction = ParameterDirection.Output; pvCommand.Parameters.Add(pvNewId); try { sqlRows = pvCommand.ExecuteNonQuery(); if (sqlRows > 0) Debug.Print("New Id Inserted = ", pvCommand.Parameters["@NewId"].Value.ToString()); } catch (Exception e) { Debug.Print("Insert Exception Type: {0}", e.GetType()); Debug.Print(" Message: {0}", e.Message); } } 

Modifiqué ligeramente su procedimiento almacenado (para usar SCOPE_IDENTITY ) y se ve así:

 CREATE PROCEDURE usp_InsertContract @ContractNumber varchar(7), @NewId int OUTPUT AS BEGIN INSERT INTO [dbo].[Contracts] (ContractNumber) VALUES (@ContractNumber) SELECT @NewId = SCOPE_IDENTITY() END 

Intenté esto y funciona bien (con ese procedimiento almacenado modificado):

 // define connection and command, in using blocks to ensure disposal using(SqlConnection conn = new SqlConnection(pvConnectionString )) using(SqlCommand cmd = new SqlCommand("dbo.usp_InsertContract", conn)) { cmd.CommandType = CommandType.StoredProcedure; // set up the parameters cmd.Parameters.Add("@ContractNumber", SqlDbType.VarChar, 7); cmd.Parameters.Add("@NewId", SqlDbType.Int).Direction = ParameterDirection.Output; // set parameter values cmd.Parameters["@ContractNumber"].Value = contractNumber; // open connection and execute stored procedure conn.Open(); cmd.ExecuteNonQuery(); // read output value from @NewId int contractID = Convert.ToInt32(cmd.Parameters["@NewId"].Value); conn.Close(); } 

¿Esto también funciona en tu entorno? No puedo decir por qué su código original no funcionará, pero cuando hago esto aquí, VS2010 y SQL Server 2008 R2, simplemente funciona perfectamente …

Si no recupera un valor, entonces sospecho que los Contracts tabla podrían no tener realmente una columna con la propiedad IDENTITY .

Antes de cambiar el procedimiento almacenado, compruebe cuál es el resultado de su actual. En SQL Server Management, ejecute lo siguiente:

 DECLARE @NewId int EXEC @return_value = [dbo].[usp_InsertContract] N'Gary', @NewId OUTPUT SELECT @NewId 

Vea lo que devuelve. Esto puede darle algunos indicios de por qué su param no está lleno.

Procedimiento almacenado………

 CREATE PROCEDURE usp_InsertContract @ContractNumber varchar(7) AS BEGIN INSERT into [dbo].[Contracts] (ContractNumber) VALUES (@ContractNumber) SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY] END 

DO#

 pvCommand.CommandType = CommandType.StoredProcedure; pvCommand.Parameters.Clear(); pvCommand.Parameters.Add(new SqlParameter("@ContractNumber", contractNumber)); object uniqueId; int id; try { uniqueId = pvCommand.ExecuteScalar(); id = Convert.ToInt32(uniqueId); } catch (Exception e) { Debug.Print(" Message: {0}", e.Message); } } 

EDITAR: “Todavía obtengo un valor DBNull … No se puede convertir objetos de DBNull a otros tipos. Volveré a ocuparme mañana. Me voy a mi otro trabajo”.

Creo que la columna Id en su tabla SQL no es una columna de identidad.

enter image description here

En su código C #, está utilizando la transacción para el comando. Simplemente realice la transacción y luego acceda a su valor de parámetro, obtendrá el valor. Trabajó para mi. 🙂