1

I have written a tool in C# that allows my manager to run a set of SQL commands at the end of every month. The SQL commands are stored in a database so I can easily maintain it as requirements change. Each successive command may or may not be allowed to run based on the success of the previous command.

Actually the command stored in my database is just a SQL command that calls a stored procedure where all the complex stuff is.

I'm using the command C# ExecuteNonQuery() and this usually returns a -1 if it fails and something else if it succeeds (so far so good). It has been working like this for years.

Now comes the maintenance bit.

All of my stored procedures have previously been updating data in my database. I now need to add a stored procedure that checks if something already exists in the database. If it doesn't exist or fails completely I want to return -1 or something else if the data does exist.

I have tried turning SET NOCOUNT OFF and that didn't help and I think I have narrowed it down the the fact that my latest procedure doesn't update anything and therefore ExecuteNonQuery sees this as a failure.

I have run the commands in Management Studio and they report success as expected. The current command even returns "1 row(s) effected" in the messages tab.

Here is the stored procedure code so you can see what I have tried so far. I'm trying to avoid having to modify my C# program so that uses different commands depending on the type of SQL called.

Does anyone have ideas?

USE [Billing]
GO
/****** Object:  StoredProcedure [dbo].[Billing_Test_Uncharged_Entries]    
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- 
ALTER PROCEDURE [dbo].[Billing_Test_Uncharged_Bing_Entries] 
    -- Add the parameters for the stored procedure here
AS

DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;

BEGIN TRY
    --SET NOCOUNT ON;
    Set NOCOUNT OFF;

    -- Insert statements for procedure here
    --SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>
    If Not Exists
    (
        SELECT [lSundriesID]
        FROM [Strata].[dbo].[vjrSundries]
        where 
        lFeeCodeID = '77' And
        -- lFeeCodeID = '999' And  --(Use this line to force an error during testing)
        lMonthfeeApplies is null
    )
    Begin
        --print 'Nothing to see here'
        --Return -1

        SELECT 
            @ErrorMessage = 'No FeeCodeID=77 Items found, Has the Bing EP Mailroom import process been run in Sundries',
            @ErrorSeverity = 11,
            @ErrorState = 1;

            RAISERROR (
                @ErrorMessage,  -- Message text
                @ErrorSeverity, -- Severity
                @ErrorState     -- State
            );
    End
    Else
    Begin
        Select 'Found Something'
    End
END Try
Begin Catch

            SELECT 
                @ErrorMessage = ERROR_MESSAGE(),
                @ErrorSeverity = ERROR_SEVERITY(),
                @ErrorState = ERROR_STATE();

                RAISERROR (@ErrorMessage, -- Message text.
                   @ErrorSeverity, -- Severity.
                @ErrorState -- State.
                );
End Catch
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
David P
  • 411
  • 7
  • 21

2 Answers2

0

ExecuteNonQuery returns the number of rows affected by a DELETE, INSERT or UPDATE statement - because that's what it's used for typically. It does NOT return the number of rows selected from a SELECT statement - instead it returns -1.

BUT: since the ExecuteNonQuery call doesn't give you a chance to actually get the data returned, it really doesn't make much sense with a SELECT - you should use an ExecuteReader call instead, which returns a SqlDataReader which you can then use to iterate over the data returned by the SELECT statement and use that data in whichever way you need it.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    I don't really need the data returned, the test is considered to be successful if the Select statement finds any records matching the criteria. I can see how this is a special case and doesn't really match the purpose of ExecuteNonQuery. I'll make some changes to my C# code so that I can choose the type of query execution based on the actual requirements. I'm trying to keep this generic so my C# program can be used to perform any test or execute any command on the Database. Who knows maybe I'll publish it one day :) I'll mark this as answered once I get it to work. Thanks – David P Oct 22 '18 at 04:35
0

For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers.

For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.

if we run stored procedure via ExecuteNonQuery it will be returned -1 always

see this page also.

afshar
  • 523
  • 4
  • 16
  • I'm not sure I agree with the statement "Stored Procedure run via ExecuteNonQuery will always return -1" I'm doing exactly this and at least for insert statements it works. It looks like I have to edit my program and include a switch that makes a call to ExecuteReader when my SQL is a select statement. – David P Oct 22 '18 at 04:32
  • the last paragraph of this page can help you https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.executenonquery?redirectedfrom=MSDN&view=netframework-4.7.2#System_Data_SqlClient_SqlCommand_ExecuteNonQuery – afshar Oct 22 '18 at 06:31