Skip to content

Remarks for ExecuteNonQuery additional reasons to return -1 #1876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 10, 2019
Merged

Remarks for ExecuteNonQuery additional reasons to return -1 #1876

merged 3 commits into from
Apr 10, 2019

Conversation

joelpaula
Copy link
Contributor

Summary

Added a remark to ExecuteNonQuery for an additional reason for it to return -1 - the connection's NO COUNT is ON.

Added a remark to ExecuteNonQuery for an additional reason for it to return -1 (the connection's NO COUNT is ON).
@rpetrusha
Copy link

@divega, can you review this PR, please?

@rpetrusha rpetrusha added this to the February 2019 milestone Feb 20, 2019
@BillWagner BillWagner requested a review from divega February 22, 2019 14:40
@divega
Copy link
Contributor

divega commented Feb 26, 2019

Copying the proposed change (text added in bold) here to make the review easier :

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 the statement sets NOCOUNT as ON (a SET NOCOUNT ON statement is part of the statement) or the connection is currently with the NOCOUNT mode ON, the return value will also be -1.

  1. Unfortunately, I don't think the API documentation for SqlCommand recognizes the fact that multiple statements concatenated with ";" are supported, so we pretend that they are the same thing. But inside the parenthesis it becomes evident that we are using the word "statement" to mean two different things: the content of the CommandText property, and an individual T-SQL statement inside that CommandText.

  2. Also, the sentence before the parenthesis and inside the parenthesis seem redundant. I would leave one or the other.

  3. I am not sure that implying that any time SET NOCOUNT ON is used the return value will be -1 is going to help in all cases. SET NOCOUNT ON is recommend in the body of triggers or stored procedures to avoid impacting the count of rows affected with side effects. Rows affected while the setting is enabled should not contribute to the final count, but any rows affected before or after, AFAIR, should.

  4. Perhaps this is complex enough that having multiple paragraph is justified.

I suggest to tweak it some something like this:

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.

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.

When SET NOCOUNT ON is set on the connection (before or as part of executing the command, or as part of a trigger initiated by the execution of the command) the rows affected by individual statements stop contributing to the count of rows affected returned by this method.

If no statement are detected that contribute to the count, the return value is -1. If a rollback occurs, the return value is also -1.

cc @David-Engel this is for SqlClient specifically, so you may want to review or ask someone in your team to review.

cc @roji in case this is interesting for him.

Copy link

@rpetrusha rpetrusha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joelpaula, I'm sorry that it's taken so long for me to respond. Would you like to make the changes suggested by @divega?

Applying the changes suggested by @divega, to make it super clear how the NOCOUNT and other circumstances may affect the number of affected rows return by ExecuteNonQuery.
@dnfclas
Copy link

dnfclas commented Apr 2, 2019

CLA assistant check
All CLA requirements met.

Copy link
Contributor

@divega divega left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Content looks good to me.

@roji
Copy link
Member

roji commented Apr 2, 2019

Missed this back in February... It's definitely great to have this level of documentation on what actually happens in SqlClient.

Just out of curiosity @divega: do the extra rows updated by triggers interfere with our optimistic concurrency in any way, or we are checking for zero vs. one or more rows updated?

@divega
Copy link
Contributor

divega commented Apr 2, 2019

IIRC EF6 and EF Core check for exactly 1 record affected per intended change, but @AndriySvyryd may remember better than I 😄

Generally SET NOCOUNT ON as the first line of a trigger is considered the best practice.

@AndriySvyryd
Copy link
Member

@roji We check for exactly 1 currently, but we could relax this. dotnet/efcore#12064

Copy link

@rpetrusha rpetrusha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much, @joelpaula, for contributing to the dotnet/dotnet-api-docs repo and enriching the documentation. I've left one minor suggestion for you to consider. Once you address it, I'll merge.

@roji
Copy link
Member

roji commented Apr 2, 2019

@AndriySvyryd it's just a thought, relaxing it seems like it would allow optimistic concurrency and rowcount-enabled triggers to work together.

@divega
Copy link
Contributor

divega commented Apr 4, 2019

@AndriySvyryd it's just a thought, relaxing it seems like it would allow optimistic concurrency and rowcount-enabled triggers to work together.

We could, but I think the recommendation to use SET NOCOUNT ON o triggers is reasonable and well-know (at least I remember learning about it since my RDO days), there is a risk that for UPDATE or DELETE statements to actually affect more than one row if you lie about the primary keys, plus I don't remember right now customers asking for it 😄

Co-Authored-By: joelpaula <joelpaula@hotmail.com>
@joelpaula joelpaula requested a review from stevestein as a code owner April 5, 2019 09:54
@roji
Copy link
Member

roji commented Apr 5, 2019

@divega makes sense.

@rpetrusha
Copy link

Thanks, @joelpaula, for making the additional changes. I'll approve and merge your PR now. The changes should be live on docs.microsoft.com in the next day or two.

@rpetrusha rpetrusha merged commit bac390e into dotnet:master Apr 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants