I have async issue with my below query. I have singleton context and i am trying to execute below query:
var query = await (from parent in Context.ParentTable
join child in Context.ChildTable
on parent.ID equals child.ID
into allResult
from ResultValue in allResult.DefaultIfEmpty()
where ResultValue.TenantId == tenantId
select new Result
{
Code = parent.Code,
Type = parent.Type,
ID = ResultValue == null ? 0 : ResultValue.Id
}).ToListAsync();
My singleton context looks like this:
public class BaseRepository
{
private readonly IConfigurationContextFactory configurationContextFactory;
private IConfigurationContext context;
protected IConfigurationContext Context
{
get
{
return context ?? (context = configurationContextFactory.Context);
}
}
public BaseRepository(IConfigurationContextFactory configurationContextFactory)
{
this.configurationContextFactory = configurationContextFactory;
}
}
The configuration context factory returns Context like this:
private ConfigurationContext Get()
{
logger.WriteEntrySync(LogLevel.Information,
null != context ? "Config Context: Using existing context." : "Config Context: Wiil create new context.");
return context ?? (context = new ConfigurationContext(connectionString));
}
In this i get intermittent issue with following error:
A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.
In general, one would use async await when you want to keep the currently running thread from blocking. This frees the thread for other tasks (like updating the UI), while we await the asynchronous result.
A DbContext instance represents a session with the database and can be used to query and save instances of your entities. DbContext is a combination of the Unit Of Work and Repository patterns. Entity Framework Core does not support multiple parallel operations being run on the same DbContext instance.
An AsyncContext is created and initialized by a call to ServletRequest#startAsync() or ServletRequest#startAsync(ServletRequest, ServletResponse) . Repeated invocations of these methods will return the same AsyncContext instance, reinitialized as appropriate.
Async LINQ operators Note that there are no async versions of some LINQ operators such as Where or OrderBy, because these only build up the LINQ expression tree and don't cause the query to be executed in the database. Only operators which cause query execution have async counterparts.
I have singleton context
This is your problem. DbContext
isn't thread-safe, and is designed to execute one query at a time. Since you're sharing your DbContext
, you're probably attempting to invoke another query concurrently, which isn't "legal" in DbContext
terms.
You can even see it in the remarks of ToListAsync
:
Multiple active operations on the same context instance are not supported. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context.
What you should do is not re-use your context with a global singleton, by create a new context each time you want to query your database.
Edit:
Instead of getting a single Context
via your factory method, simply allocate a new one for every query:
using (var context = new ConfigurationContext(connectionString))
{
var query = await (from feature in context.Features
join featureFlag in context.FeatureFlags
on feature.FeatureId equals featureFlag.FeatureId
into allFeatures
from featureFlagValue in allFeatures.DefaultIfEmpty()
where featureFlagValue.TenantId == tenantId
select new BusinessEntities.FeatureFlag
{
Code = feature.Code,
Type = feature.Type,
FeatureFlagId = featureFlagValue == null ? 0 : featureFlagValue.FeatureFlagId
}).ToListAsync();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With