Usando parâmetros de saída do procedimento armazenado em c #

Estou tendo um problema ao retornar um parâmetro de saída de um procedimento armazenado do Sql Server para uma variável C #. Eu li os outros posts sobre isso, não apenas aqui, mas em outros sites, e não consigo fazê-lo funcionar. Aqui está o que eu tenho atualmente. Atualmente estou apenas tentando imprimir o valor que retorna. O código a seguir retorna um valor nulo. O que eu estou tentando retornar é a chave primária. Eu tentei usar @@IDENTITY e SCOPE_INDENTITY() (isto é, SET @NewId = SCOPE_IDENTITY() ).

Procedimento armazenado:

 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 

Abrindo o database:

 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; } 

Executando o 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); } } 

Eu modifiquei um pouco seu procedimento armazenado (para usar o SCOPE_IDENTITY ) e ficou assim:

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

Eu tentei isso e funciona muito bem (com esse procedimento armazenado 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(); } 

Isso funciona no seu ambiente também? Eu não posso dizer por que seu código original não vai funcionar – mas quando eu faço isso aqui, VS2010 e SQL Server 2008 R2, ele simplesmente funciona perfeitamente ….

Se você não receber de volta um valor – então eu suspeito que sua tabela Contracts pode não ter realmente uma coluna com a propriedade IDENTITY nela.

Antes de alterar o procedimento armazenado, verifique qual é a saída do seu atual. No Gerenciamento do SQL Server, execute o seguinte:

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

Veja o que ele retorna. Isso pode lhe dar algumas dicas de porque seu parâmetro de saída não está preenchido.

Procedimento armazenado………

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

C #

 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); } } 

EDIT: “Eu ainda recebo de volta um valor de DBNull …. Objeto não pode ser convertido de DBNull para outros tipos. Vou levar isso de novo amanhã. Estou fora para meu outro trabalho”

Eu acredito que a coluna Id na sua tabela SQL não é uma coluna de identidade.

insira a descrição da imagem aqui

No seu código c #, você está usando a transação para o comando. Apenas confirme a transação e depois disso, acesse seu valor de parâmetro, você obterá o valor. Trabalhou para mim. 🙂