SET NO Count ON in SQl Server Causes an issue with ExecuteNonQuery - c#

According to the most of the SQL texts that I have seen
SET NoCount ON
Add's to the DB performance and DBA's don't like to see it OFF.
However in the ASP.NET that i'm dealing with , this causes
Calling to the stored procedures using ExecuteNonQuery always result in -1.
Is this a known issue and if so what is the workaround?
So the question is how have SET NoCount ON and then ExecuteNonQuery return number of rows affected.
This question is for 'ExecuteNonQuery' only. I know I can use ExecuteScalar and get the ##RowCount

What else did you expect? You explicitely tell the database to not count the rows and then you are asking why the counted rows are not returned?
The database does not deliver the number of rows affected, because you turned it off. That's neither an issue nor a bug, that's the whole point of what you did.

Since you asked the db not to return that information, it does exactly what you said.
You could try to prefix your queries with SET NOCOUNT OFF and postfix with SET NOCOUNT ON to get the number of rows for specific cases

Related

How to get number of rows affected by ExecuteNonQuery and ignore rows of triggers?

I am using ExecuteNonQuery to run an insert proc, it returns 2, but in actual I am inserting only 1 record. I am getting 1 extra due to trigger. Is there anyway that I get only actual number of rows affected. I do not want the rows affected by trigger.
If you don't have it already, disable counting rows in your trigger:
SET NOCOUNT ON
For example:
CREATE TRIGGER [dbo].[triggerName] ON [dbo].[TableName]
AFTER INSERT
AS
SET NOCOUNT ON;
......
MSDN
please refer below mention Image
However, the MSDN article on this function states:
For UPDATE, INSERT, and DELETE statements, the return value is the number
of
rows affected by the command. For all other types of statements, the
return
value is -1. If a rollback occurs, the return value is also -1.
See...
enter link description here

what is the meaning of A trigger returned a resultset and/or was running with SET NOCOUNT OFF

I am getting this exception:
A trigger returned a resultset and/or was running with SET NOCOUNT OFF while another outstanding result set was activ
I want to know what is the meaning of that, with an example and how to avoid it (without SET NOCOUNT ON - as i need to know number of rows affected).
Here more explanation of what I am doing?
Let us say I have a table in my SQL Server DB with the name AccNodesBal and I have 3 triggers on that table:
FOR UPDATE
INSERT
DELETE
I am using ADO.net as data layer. As you know, 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.
In my application (code) I am using ExcecuteNonQuery and get the number of rows affected in an int variable and validate that it's 2 to ensure that the trigger is fired and everything is logged.
But I am getting this error:
A trigger returned a resultset and/or was running with SET NOCOUNT OFF
while another outstanding result set was active.
After searching I have found that I have to use SET NOCOUNT ON keyword in my triggers. Unfortunately this will not work with my application, as the trigger will not now return any values of affected rows. Does anyone know another approach to get the number of rows affected from updates statement and trigger without using SET NOCOUNT ON?
Here is my code
int recCount = adpt.cmdMovementUpdate(
amtType == EFG.Acc.AccNodeService.Contracts.Entities.AmountType.Debit ? 0 : Amount,
amtType == EFG.Acc.AccNodeService.Contracts.Entities.AmountType.Debit ? Amount : 0,
NodeID, PeriodID, Convert.ToInt16(CurrCode), Convert.ToByte(BalCurrType));
where adpt the TableAdapter contains my sql Update command query and it's implemented in a WCF service, which is consumed by a webservice, and the application consume this webservice.
After searching i see that it is recommended to use SET NOCOUNT ON, but that will not work for me as i have validation in my WCF service that depends on result of row affected from ExecuteNonQuery.
Could you try putting SET NOCOUNT OFF towards the end of the trigger and see if it resolves your issue. Also take a look at the following
http://social.msdn.microsoft.com/Forums/en-US/sqlintegrationservices/thread/5ee185e6-1980-4209-87f6-abeb9c5933fa/

What does value returned from 'IDbCommand.ExecuteNonQuery' represent?

I am using ADO.net to call stored procedures to perform insertions into a Sybase database, and I want to include unit tests to ensure that the insert calls are working correctly.
According to the spec:
IDbCommand.ExecuteNonQuery()
Returns: The number of rows affected.
As each stored procedure is inserting one row, I am checking that the value returned == 1.
However, each procedure returns a different value, ranging from 3 to 8.
So, what exactly does the phrase 'The number of rows affected' mean?
I should sepcify that the only statements in the procs are Set, Insert, Print and Return, and the only statement that doesn't seem to affect the return value is Insert!
Thanks.
Then your procedure doing something, it can arise some triggers and system updates, depending on your inner logic. And this number is the sum of this affected rows.
More info:
http://www.sqlhacks.com/Retrieve/Row_Count
Without any knowledge of the Sybase provider, a likely answer is that ExecuteNonQuery returns the cumulative sum of 'The number of rows affected' messages returned by the SQL statement. In SQL Server, ##ROWCOUNT returns the number of rows affected by the last statement.
I found this comment in the SqlCommand.cs source on the ExecuteNonQuery return value, but didn't actually verify it:
// sql reader will pull this value out for each NextResult call. It is not cumulative
// _rowsAffected is cumulative for ExecuteNonQuery across all rpc batches
internal int _rowsAffected = -1; // rows affected by the command
In SQL Server, you can use SET NOCOUNT in the stored procedures to control how many count messages is returned. ExecuteNonQuery returns -1 if no messages are returned, by setting SET NOCOUNT ON at the beginning.
SET and RETURN do not send messages to same output stream where count messages go, but PRINT does. Printed strings shouldn't affect ExecuteNonQuery integer return value, but I can't really tell.
The point is that it is better to use T-SQL output parameters to calculate interesting rows than to rely on the ExecuteNonQuery return value. Alternative to output parameters is to use the SELECT resultset and ExecuteScalar
See Also
Overriding rows affected in SQL Server using ExecuteNonQuery?
According to MSDN the return value of 'ExecuteNonQuery' is not relevant for stored procedure execution.
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. For all other types of statements, the return value is -1.
You can instead use stored procedure return values or output parameters to obtain the desired value.
Just verify your sql routine logic if its having some dependency logic in case it adds more that 1 rows on certain condition.

Show how many rows were deleted

I use C# program and my database is in SQL server 2008.
When user deleted some rows from database, I want to show him/her in windows application how many rows deleted.
I want to know how I can send SQL message to C# and show it for user.
For example when I deleted 4 rows from table, SQL show message like (4 row(s) affected). Now I want to send number 4 to my C# program. How can I do it? Thank you.
If you are using SqlCommand from your .NET application to perform your delete/update, the result of ExecuteNonQuery() returns the number of rows affected by the last statement of the command.
See http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx.
If you're using the System.Data.SqlClient.SqlCommand.ExecuteNonQuery method or System.Data.Common.DbCommand.ExecuteNonQuery method, then the return value should be the number of rows affected by your statement (the last statement in your command, I think).
There is a caveat to this...if you execute a batch or stored procedure that does SET NOCOUNT ON, then the number of rows affected by each statement is not reported and ExecuteNonQuery will return -1 instead.
in T-SQL, there is a ##rowcount variable that you can access in order to get the number of rows affected by the last statement. Obviously you would need to grab that immediately after your DELETE statement, but I believe you could do a return ##rowcount within your T-SQL if you are using SET NOCOUNT ON.
Alternatives would be to return the value as an OUTPUT parameter, especially if you have a batch of multiple statements and you'd like to know how many rows are affected by each. Some people like to use the T-SQL RETURN statement to report success/failure, so you may want to avoid returning "number of rows affected" for consistency's sake.
I imagine you would want to do a select "count" on the delete statement before you issue the delete, then capture the number and manipulate it as needed.
Use the ##RowCount SQL Environment variable.
You can return it from a Stored Procedure if you are using them.

SET NOCOUNT ON and reading messages using C# and ADO.NET

SET NOCOUNT ON stops the message that shows the count of the number of rows affected by a Transact-SQL statement or stored procedure from being returned as part of the result set.
a) How can you read these messages using C# and ADO.NET ( I assume C# code reading these messages is the same regardless of whether T-SQL statements were executed in a stored procedure, batch or… )?
b) Assuming stored procedure contains several statements, how can your C# code identify to what SQL statement does particular messages refer to?
Thank you
Informational messages (like the rows affected count info) are reported in ADO.Net through the SqlConnection.InfoMessage event. Add a delegate to the event and will be invoked whenever the server transmits an informational message (ie. any error message with severity bellow 10).
there is no way to associate informational messages like afffected count info with the source. You're going to have to do it based on knowledge of the logic and understand that the first message refers to the first update, the second message to the second update etc.
Relying on affected rows count in the client is generaly a bad practice. The many issues ORM layers like NHibernate and ADO.Net datasets have when SET NOCOUNT ON is turned on just shows how problematic this practice is.
Don't rely on it. Best practice is SET NOCOUNT ON (discussed with my question here)
When you load your datatable, use .Count.
Use an OUTPUT parameter to pass ##ROWCOUNT back (or as a dataset)
Take a look at this question and answers. You can't do (b) above without adding some code in your TSQL that captures the ##rowcount and outputs it in some manner (like a resultset that you could read from).
One option is in your stored procedure is to include variables that you will pass back statement counts. You can do by creating your procedure with the needed OUTPUT parameters.
FIRST SQL HERE
#FirstSQLCount = ##ROWCOUNT
SECOND SQL HERE
#SecondSQLCount = ##ROWCOUNT

Categories

Resources