web-dev-qa-db-fra.com

Utilisation de paramètres de sortie de procédure stockée en C #

Je rencontre un problème pour renvoyer un paramètre de sortie d'une procédure stockée Sql Server dans une variable C #. J'ai lu les autres articles à ce sujet, pas seulement ici, mais sur d'autres sites, et je ne peux pas le faire fonctionner. Voici ce que j'ai actuellement. Actuellement, j'essaie simplement d'imprimer la valeur qui revient. Le code suivant renvoie une valeur null. Ce que j'essaie de retourner est la clé primaire. J'ai essayé d'utiliser @@IDENTITY et SCOPE_INDENTITY() (c'est-à-dire SET @NewId = SCOPE_IDENTITY()). 

Procédure stockée:

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

Ouverture de la base de données:

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

Exécuter la commande:

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

J'ai légèrement modifié votre procédure stockée (pour utiliser SCOPE_IDENTITY) et cela ressemble à ceci:

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

    SELECT @NewId = SCOPE_IDENTITY()
END

J'ai essayé ceci et cela fonctionne très bien (avec cette procédure stockée modifiée):

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

Est-ce que cela fonctionne aussi dans votre environnement? Je ne peux pas dire pourquoi votre code original ne fonctionnera pas - mais lorsque je le fais ici, VS2010 et SQL Server 2008 R2, cela fonctionne parfaitement ...

Si vous ne récupérez pas de valeur, alors je soupçonne que votre table Contracts ne contient peut-être pas vraiment une colonne avec la propriété IDENTITY.

104
marc_s

Avant de changer la procédure stockée, veuillez vérifier quelle est la sortie de votre procédure actuelle. Dans SQL Server Management, exécutez les actions suivantes:

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

Voir ce qu'il retourne. Cela peut vous donner une idée de la raison pour laquelle votre paramètre de sortie n'est pas rempli.

3
TarasB

Procédure stockée.........

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: "Je récupère toujours une valeur DBNull ... L'objet ne peut pas être converti de DBNull vers d'autres types. Je reprendrai cela demain. Je pars pour mon autre travail"

Je crois que la colonne Id de votre table SQL n'est pas une colonne d'identité.  

enter image description here

1
Jeremy Thompson

Dans votre code C #, vous utilisez transaction pour la commande . Commencez par la transaction, puis accédez à la valeur de votre paramètre pour obtenir la valeur . :) 

0
Nitin