简体   繁体   中英

Stored Procedure not returning Value - C#

I have this stored procedure:

ALTER PROCEDURE [dbo].[DeleteFromSchoolMain]
    @TblName VARCHAR(50),
    @MainID VARCHAR(10),
    @TblCol VARCHAR(50),
    @rowsCount INT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @RelTbl AS Nvarchar(50)
    DECLARE @ColForFK AS Nvarchar(50)
    DECLARE @TblMaterial AS NVARCHAR(50)
    DECLARE @ColMaterialID AS NVARCHAR(50)
    DECLARE @ColMaterialFK AS NVARCHAR(50)
    DECLARE @cmdForMaterial AS NVARCHAR(max)
    DECLARE @TblSubject AS NVARCHAR(50)
    DECLARE @ColSubjectID AS NVARCHAR(50)
    DECLARE @ColSubjectFK AS NVARCHAR(50)
    DECLARE @cmdForSubject AS NVARCHAR(max)

    Set @ColForFK = SUBSTRING(@TblCol,1, DATALENGTH(@TblCol)-2)
    Set @ColForFK = @ColForFK+'FK'

    DECLARE @cmd AS NVARCHAR(max)
    DECLARE @TempCount int

    SET @MainID = ''''+@MainID+ ''''

    SET @RelTbl = 'ClassSubMatRelation'
    --For Class Material
    SET @TblMaterial = 'ClassMaterial'
    SET @ColMaterialID = 'ClassMaterialID'
    SET @ColMaterialFK = 'ClassMaterialFK'

    SET @cmd = N'UPDATE ' + @RelTbl + ' SET Status_Info = 0 WHERE ' +  @ColForFK + ' = ' + @MainID -- Delete from ClassRelation Table
    EXEC(@cmd)
    SET @TempCount = @@ROWCOUNT
    SET @rowsCount = @TempCount + @rowsCount;

    SET @cmd = N'UPDATE ' + @TblName + ' SET Status_Info = 0 WHERE ' +  @TblCol + ' = ' + @MainID -- Delete from Main Table
    EXEC(@cmd)
    SET @TempCount = @@ROWCOUNT 
    SET @rowsCount = @TempCount + @rowsCount;

    -------------------------------------Board-----------------------------------
    IF (@TblName = 'Board')
    BEGIN

        SET @cmdForMaterial = N'UPDATE '+@TblMaterial+' Set Status_Info = 0 where '+@ColMaterialID+' in ( Select s.'+@ColMaterialFK+' from  '+@RelTbl+' s where s.' +  @ColForFK + ' = ' +  @MainID + ' AND s.ClassSubjectFK IN ( SELECT T.ClassSubjectFK FROM ' + @RelTbl + ' T WHERE  T.'+@ColForFK+' = '+ @MainID + ') and s.ClassSubjectFK NOT IN ( SELECT E.ClassSubjectFK FROM ' +@RelTbl+' E WHERE E.'+@ColForFK+' != '+ @MainID +') and s.'+@ColMaterialFK+'  is not null )'
        EXEC(@cmdForMaterial)   
        SET @TempCount = @@ROWCOUNT 
        SET @rowsCount = @TempCount + @rowsCount;
        SET @TempCount = 0;


        --For Class Subject
        SET @TblMaterial = 'ClassSubject'
        SET @ColMaterialID = 'ClassSubjectID'
        SET @ColMaterialFK = 'ClassSubjectFK'

        SET @cmdForMaterial = N'UPDATE '+@TblMaterial+' Set Status_Info = 0 where '+@ColMaterialID+' in ( Select s.'+@ColMaterialFK+' from  '+@RelTbl+' s where s.' +  @ColForFK + ' = ' +  @MainID + ' AND s.ClassSubjectFK IN ( SELECT T.ClassSubjectFK FROM ' + @RelTbl + ' T WHERE  T.'+@ColForFK+' = '+ @MainID + ') and s.ClassSubjectFK NOT IN ( SELECT E.ClassSubjectFK FROM ' +@RelTbl+' E WHERE E.'+@ColForFK+' != '+ @MainID +') and s.'+@ColMaterialFK+'  is not null )'
        EXEC(@cmdForMaterial)   
        SET @TempCount = @@ROWCOUNT 
        SET @rowsCount = @TempCount + @rowsCount;
        SET @TempCount = 0;


    END

        ------------------------------ Class Subject ------------------------------------
    ELSE IF (@TblName = 'ClassSubject')
    BEGIN                   

        SET @cmdForMaterial = N'UPDATE '+@TblMaterial+' Set '+@TblMaterial+'.Status_Info = 0 from '+@TblMaterial+' tm join '+@RelTbl+' rt on rt.'+@ColMaterialFK+' = tm.'+@ColMaterialID+' where rt.'+@ColForFK+ ' = '+ @MainID
        EXEC(@cmdForMaterial)

        SET @TempCount = @@ROWCOUNT 
        SET @rowsCount = @TempCount + @rowsCount;
        SET @TempCount = 0;
    END

END
GO

And I'm executing it in C# like this:

var rowsAffected = 0;

using (SqlConnection conn = new SqlConnection(Constants.Connection))
{
     conn.Open();

     SqlCommand cmd = new SqlCommand("DeleteFromSchoolMain", conn);
     cmd.CommandType = CommandType.StoredProcedure;

     cmd.Parameters.AddWithValue("@TblName", abundleBoard.TempName);
     cmd.Parameters.AddWithValue("@MainID", abundleBoard.MainID.ToString());
     cmd.Parameters.AddWithValue("@TblCol", abundleBoard.TblCol);

     SqlParameter outputParam = new SqlParameter();
     outputParam.ParameterName = "@rowsCount";
     outputParam.SqlDbType = System.Data.SqlDbType.Int;
     outputParam.Direction = System.Data.ParameterDirection.Output;
     cmd.Parameters.Add(outputParam);

     object o = cmd.ExecuteScalar();

     if (!outputParam.Value.Equals(DBNull.Value))
     {
         rowsAffected = Convert.ToInt32(outputParam.Value);
         string q = o.ToString();
     }

     conn.Close();
}

But my problem is I'm not getting anything in output parameter. I don't understand the problem, also I feels like my stored procedure is not optimised. Is there anything I can do to make the queries execute faster? Indexing and partitioning I've done my level best already.

EDIT:

So with help of @SurjitSD and @PeterB I got a resolution:-

In my Procedure I added the line at Top :-

SET @rowsCount=0

And in c# I've changed the code like :-

 cmd.ExecuteNonQuery();
 if (!cmd.Parameters["@rowsCount"].Value.Equals(DBNull.Value))
  {
   rowsAffected = Convert.ToInt32(cmd.Parameters["@rowsCount"].Value);
  }

For Now this works fine!

You are calling ExecuteScalar in c#.

ExecuteScalar will give you firstRow and FirstColumn value returned by Select statement in procedure.

You need to use ExecuteNonQuery

After ExecuteNonQuery , you can get value like

cmd.Parameters["@rowsCount"].Value

You can also get value using ExecuteScalar if you use Select @rowsCount after set @rowsCount . Then you dont need to mention output direction to any parameter, both in sql and c#

Example with ExecuteScalar

Sql procedure

Alter procedure SomeProcedure
(
@someVariable int
:
:
)
Begin
   /*Some processing logic of procedure*/

    Select @SomeVariable //any variable Or Value from procedure needed as output in c#
End

C#

var result = cmd.ExecuteScalar();

——- Edit ——

The actual reason for not getting value in c# was (with explanation)

The parameter @rowsCount was not initialized before using. So it was null and when doing SET @rowsCount = @TempCount + @rowsCount , its actually adding something to null . And adding anything to null will be null as result.

So @rowsCount was always null . Setting @rowsCount=0 in begining of procedure helped.

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