question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

sql error when using CancellationToken and cancelling it fast multiple times

See original GitHub issue

this is my code (blazor server):

@inject IDbContextFactory<MyContext> cxf
<button type="button" id="btn1" @onclick="btnClick">Load</button>

    private CancellationTokenSource cts;
    private CancellationTokenSource prevCts;

    private async Task btnClick()
    {
        if (prevCts is not null) prevCts.Cancel();
        cts = new CancellationTokenSource();
        prevCts = cts;

        using var cx = cxf.CreateDbContext();

        var res = await cx.Lunches.ToArrayAsync(cts.Token);
        var res1 = await cx.Categories.ToArrayAsync(cts.Token);
        var res2 = await cx.Countries.ToArrayAsync(cts.Token);
    }

to get the error I’m using js to click the button multiple times instantly: $('#btn1').click().click().click() usually 3 clicks is enough to get the error

Error: Microsoft.Data.SqlClient.SqlException (0x80131904): The request failed to run because the batch is aborted, this can be caused by abort signal sent from client, or another request is running in the same session, which makes the session busy.
Operation cancelled by user.
   at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__208_0(Task`1 result)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToArrayAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
...
--- End of stack trace from previous location ---

when 3 clicks doesn’t throw the error, with about 15 I can get this error:

 Error: System.InvalidOperationException: Operation cancelled by user.
   at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__208_0(Task`1 result)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToArrayAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
...

Note when the error doesn’t occur (with 2 clicks always), I would see (in ExpressProfiler) that for the cancelled clicks only 1 db request is made and the last one makes all the requests.

Include provider and version information

EF Core version: 7 Database provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer) Target framework: (e.g. .NET 7.0) Operating system: IDE: Visual Studio 2022 17.4

Issue Analytics

  • State:closed
  • Created 9 months ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
rojicommented, Dec 15, 2022

@omuleanu what exactly is the behavior you find problematic above? When you trigger a cancellation token, the operation to which it was given is supposed to throw an OperationCanceledException - since the operation can’t complete. It’s your responsibility to catch that exception and handle appropriately (possibly exiting the button click handler right away).

Now, SqlClient specifically doesn’t throw OperationCanceledException, but instead throws a SqlException (see https://github.com/dotnet/SqlClient/issues/26); but that doesn’t seem to be what you’re complaining about (I admit the InvalidOperationException is even more problematic).

1reaction
rojicommented, Dec 15, 2022

I was thinking if I click on page 2 and while loading I click on 3 meaning I changed my mind about loading 2 and want page 3 now; so to make it a tiny bit more responsive, instead of locking until the result is back, also I was interested to learn how the Cancellation works.

You can certainly do that - swallowing cancellation exceptions and making sure things are sane in the face of concurrent updating - though I’m not sure that makes for an intuitive UI 😃

In any case, am going to go ahead and close this as it seems that everything is working as expected. But feel free to post back here with further questions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sql Error when using EF with CancellationToken in Blazor ...
Reason for using Cancellation: I'm cancelling the previous request since the user clicked again really fast on something else, so there's no ...
Read more >
Cancelling an async SqlClient operation throws ...
When using a cancellation token to cancel an SqlClient async operation, an SqlException is thrown rather than TaskCanceledException.
Read more >
Use cancellation token to cancel execution of multiple ...
The CancellationToken passed in to the action should automatically be cancelled if the client aborts the request.
Read more >
How to: Listen for Multiple Cancellation Requests | ...
This example shows how to listen to two cancellation tokens simultaneously so that you can cancel an operation if either token requests it....
Read more >
Cancel Query Rollback – SQLServerCentral Forums
I cancelled a long running update statement that was running against a large table and now sql server is rolling back changes.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found