简体   繁体   中英

C# & SQL Server stored procedures - can't get output parameter value, return value works

I would like to get a value of an output parameter of a stored procedure, but I'm getting +1 all the time. When obtaining a value by return everything's ok.

I managed to obtain a value of the output parameter using Entity Framework, however, it works really slowly. I'm attaching my stored procedure and C# code used to get the values from the stored procedures.

Stored procedure with an output parameter works fine in SQL Server.

Does someone have any idea why my code doesn't work?

Thanks for your help in advance.

Stored procedure:

Create procedure sp_CountEachNumberOccurencesOutput
    @number tinyint, 
    @count_number int output
As
    SET NOCOUNT ON

    select count(*) 
    from RawData
    where Number1 = @number or Number2 = @number or Number3 = @number

    select @count_number = count(*)

C# code for stored procedure with and output parameter which uses Entity Framework and works, but it's slow:

using (SqlConnection cn = new SqlConnection(cnStr))
{
    cn.Open();

    using (SqlCommand cmd = new SqlCommand("sp_CountEachNumberOccurencesOutput", cn))
    {
        var outParam = new SqlParameter();
        int outputValue = 0;
        outParam.SqlDbType = SqlDbType.Int;
        outParam.Direction = ParameterDirection.Output;

        DbContext dbContext = new DbContext(this.connectionString);

        var data = dbContext.Database.SqlQuery<int>("sp_CountEachNumberOccurencesOutput @number, @count_number OUT",
                   new SqlParameter("number", parameter),
                   new SqlParameter("count_number", outputValue),
                   outParam);

        outputValue = data.ToList()[0];

        return outputValue;
    }
}

C# code for stored procedure with and output parameter which doesn't work:

using (SqlConnection cn = new SqlConnection(cnStr))
{
    cn.Open();

    using (SqlCommand cmd = new SqlCommand("sp_CountEachNumberOccurencesOutput", cn))
    {
        cmd.CommandType = CommandType.StoredProcedure;

        SqlParameter param = cmd.Parameters.Add("@number", SqlDbType.Int);
        param.Direction = ParameterDirection.Input;
        param.Value = parameter;

        SqlParameter outputParameter = cmd.Parameters.Add("@count_number", SqlDbType.Int);
        outputParameter.Direction = ParameterDirection.Output;
        outputParameter.Value = 0;                   

        cmd.ExecuteNonQuery();

        cn.Close();

        int OutputValue = (int)cmd.Parameters["@count_number"].Value;

        return OutputValue;
    }
}

This code gets return value and works:

using (SqlConnection cn = new SqlConnection(cnStr))
{
    cn.Open();

    using (SqlCommand cmd = new SqlCommand("sp_CountEachNumberOccurencesReturn", cn))
    {
        cmd.CommandType = CommandType.StoredProcedure;

        SqlParameter param = cmd.Parameters.Add("@number", SqlDbType.Int);
        param.Direction = ParameterDirection.Input;
        param.Value = parameter;

        SqlParameter returnValue = new SqlParameter();
        returnValue.Direction = ParameterDirection.ReturnValue;
        cmd.Parameters.Add(returnValue);

        return Convert.ToInt32(cmd.ExecuteScalar());
    }
}

Not sure if you can assign count(*) to a parameter. It only works in the sql statement.

Perhaps try this

Create procedure sp_CountEachNumberOccurencesOutput
    @number tinyint, @count_number int output
    As
    SET NOCOUNT ON
    select @counter_number=count(*)  from RawData
                where Number1 = @number or Number2 = @number  or Number3 = @number

I used to perform this task as following:

public Int32 ExecuteGenericSP(string spName, out int errNum, out string errMsg, params object[] lstParams)
{
    Int32 returnValue;
    /* Aqui */
    SqlDatabase _sqlDatabase = new SqlDatabase(getConnectionString());
    using (DbConnection con = _sqlDatabase.CreateConnection())
    {
        DbCommand cmd = _sqlDatabase.GetStoredProcCommand(spName);
        _sqlDatabase.DiscoverParameters(cmd);
        int n = 3;

        errNum = 0;
        errMsg = "";
        cmd.Parameters["@RETURN_VALUE"].Value = 0;

        cmd.Parameters["@errNum"].Value = 0;
        cmd.Parameters["@errDes"].Value = "";

        foreach (object o in lstParams)
        {
            if (cmd.Parameters[n].DbType.ToString() == "DateTime")
                cmd.Parameters[n].Value = Convert.ToDateTime(o);
            else
                cmd.Parameters[n].Value = o.ToString();
            n++;
        }

        returnValue = _sqlDatabase.ExecuteNonQuery(cmd);

        errNum = Convert.ToInt16(_sqlDatabase.GetParameterValue(cmd, "errNum"));
        errMsg = _sqlDatabase.GetParameterValue(cmd, "errDes").ToString();
    }
    return returnValue;
}

And for instance, this is a sample of a SP:

ALTER PROCEDURE [dbo].[AUD_Insertar]
    @errNum smallint OUTPUT,
    @errDes varchar(50) OUTPUT,
    @id smallint,    
    @message varchar(MAX),
    @type char(1),
    @userId varchar(20),
    @modulo char(1)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    SET @errNum = 0;
    SET @errDes = '';

    INSERT INTO log(message, type, userId, modulo) VALUES (@message, @type, @userId, @modulo)
    IF (@@ROWCOUNT = 0)
    BEGIN
        SET @errNum = 1;
        SET @errDes = 'Error while inserting';
    END
END

I hope this can help you. Regards,

Adrian

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM