Goran
Goran

Reputation: 6518

Queuing EF queries

in a windows desktop app, where context lives as long as the view lives, what would be the best way to avoid 'A second operation started on this context before a previous asynchronous operation completed' error?

In my view model I receive an instance of repository (through constructor), which wraps a single long-lived instance of DbContext, When I need to load some data, for example, if I do it from the same method, then I can just await for each of them in the async method, which ensures they are executed synchronously.

However, imagine that I have this:

private async void SomeMethodA()
{
    await Context.GetA();
}

private async void SomeMethodB()
{
    await Context.GetB();
}

They are declared as void since they are actually some event handlers. So, my code executes SomeMethodA(), and this database call could require 2 seconds. So, code execution returns to UI thread, and then something (user or code) triggers SomeMethodB(), which is going to raise above mentioned exception.

What would be the best way to ensure that async database calls are queued? is the repository the best place to handle this?

Upvotes: 1

Views: 1097

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456437

what would be the best way to avoid 'A second operation started on this context before a previous asynchronous operation completed' error?

Always await your asynchronous calls.

I can just await for each of them in the async method, which ensures they are executed synchronously.

They'll be executed asynchronously, not synchronously. However, they'll be executed serially (one at a time), which I think is what you meant.

They are declared as void since they are actually some event handlers.

And that's your problem. They must be awaited. They cannot be event handlers, sorry. You'll have to modify this part of the application design. Even if you work around this (e.g., by having multiple db connections open per request), you'll still run into problems due to async void with the "An asynchronous module or handler completed while an asynchronous operation was still pending" exception.

code execution returns to UI thread

There's no UI thread here. The execution just returns to the caller.

Upvotes: 2

Peter Bill
Peter Bill

Reputation: 528

You may be better to make your context local to the methods that use it, as described in https://msdn.microsoft.com/en-us/data/jj729737.aspx and several SO answers. I don't know much about await, but my first guess would be something like:

private async void SomeMethodA()
{
    using (var myContext = new Context()) // or, possibly, new Entities()
    {
        await myContext.GetA();
    }
}

Upvotes: 1

Related Questions