Skip to content
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

Bug in SqlCommand.ExecuteNonQueryAsync() #536

Closed
christian-ruud opened this issue Apr 23, 2020 · 12 comments
Closed

Bug in SqlCommand.ExecuteNonQueryAsync() #536

christian-ruud opened this issue Apr 23, 2020 · 12 comments

Comments

@christian-ruud
Copy link

When calling await command.ExecuteReturnValueAsync() inside a using block I get an exception saying a task was cancelled.

If I call await Task.Delay(100) before the end of the using scope, the call succeeds.

Similarly, if the call is to a stored procedure with a return value, I get a NullReferenceException if I attempt to read the return value without delaying first.

@Wraith2
Copy link
Contributor

Wraith2 commented Apr 23, 2020

ExecuteReturnValueAsync isn't a method this library provides. Is it a user extension you've written or do you have the wrong name? Can you provide a simple example piece of code to repro the error?

@christian-ruud
Copy link
Author

Sorry, seems I was a bit quick and typed the name of the wrong method. The problem is with ExecuteNonQueryAsync.

The following code examples are shortened versions of code taken from an IDisposable class. The containing class is instatiated with a using scope, and disposes all disposable objects in its Dispose method.

In the example below an exception is thrown stating that a task was cancelled:

 try
 {
      return await command.ExecuteNonQueryAsync();
 }
 catch (Exception exception)
 {
      // omitted for brevity
      throw;
 }
 finally
 {
       // omitted for brevity
       await connection.CloseAsync();
 }

If I do this instead it works as expected:

var result = await command.ExecuteNonQueryAsync();
await Task.Delay(100);
return result;

The method ExecuteReturnValueAsync is, quite correctly, a method I've written that resides in a differerent class, but this method also experiences a consequence of what I believe is the same bug:

await command.ExecuteNonQueryAsync();
try
{
    // the below line throws a NullReferenceException unless a delay is introduced.
    return Convert.ToInt32(command.Parameters["RETURN_VALUE"].Value);
}
finally
{
    await connection.CloseAsync();
}

@cheenamalhotra
Copy link
Member

Hi @christian-ruud

We'll investigate and get back to you soon on this issue.

@cheenamalhotra cheenamalhotra added this to Under Investigation in SqlClient Triage Board Jun 18, 2020
@christian-ruud
Copy link
Author

Hi,

I recently discovered the Microsoft.Data.SqlClient implementation and decided to test if this library has the same bug.
It does; with a slight variation. I only tested one of the scenarios, but I got an InvalidOperationException instead, stating that the connection is closed.

The underlying problem seems to be the same: When calling await ExecuteNonQueryAsync it proceeds to the next instruction before the awaited operation is actually complete. Obviously switching await ExecuteNonQueryAsync(); for just ExecuteNonQuery(); works fine in both libraries.

@cheenamalhotra
Copy link
Member

cc @DavoudEshtehari

@christian-ruud
Copy link
Author

Is there any progress on this one?

@DavoudEshtehari
Copy link
Member

Hi Christian,
I didn't see any exception with your sample code.
We have a work in progress for a similar exception at PR #579. Can I ask you to give it a try with your source code if your project is under .NetCore framework?
If It doesn't work for you, please provide a repro app with its stack trace for more investigations.

@christian-ruud
Copy link
Author

This is getting really weird.

I copied the failing code into LinqPad to create a simple piece of code you could test, but so far I've been unable to reproduce the error in LinqPad.

However, I still get the exception in the original codebase . In this case that's
Blazor Server -> .net standard 2.1 dll -> .net standard 2.1 dll. I haven't tried the PR, as I want to predicably reproduce with a code snippet first.

Essentially

command.ExecuteNonQuery() works both in production code and code snippet
await commandExecuteNonQueryAsync() works in code snippet but fails in production code.

The code is otherwise identical.

It seems like it could be dependant on load, perhaps? Or maybe the database? How much data is in the table? Maybe it's different for a web project somehow?

I'll keep trying to figure out the circumstances under which the error is triggered.
I can think of the following things to try, would be great if you have any suggestions:

  • I'll try making a console app instead of using LinqPad, in case it gives me different results.
  • I'll try using a blazor app to reproduce in case it gives me different result
  • I'll try making the calls against the actual production database.

@cheenamalhotra
Copy link
Member

@christian-ruud

You may also take a glance at some of the open issues if they are related to what you are experiencing.
Let us know when you get the issue reproduced in an isolated environment.

@cheenamalhotra cheenamalhotra moved this from Under Investigation to Waiting for customer in SqlClient Triage Board Sep 2, 2020
@cheenamalhotra
Copy link
Member

@christian-ruud

Do you have any update on this issue?

@christian-ruud
Copy link
Author

christian-ruud commented Jan 13, 2021 via email

@cheenamalhotra
Copy link
Member

Closing as confirmed above.

SqlClient Triage Board automation moved this from Needs More Info to Closed Jan 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

No branches or pull requests

4 participants