实体框架异步问题上下文或查询? [英] Entity framework async issues context or query?

查看:237
本文介绍了实体框架异步问题上下文或查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面的查询中出现异步问题。我有单例上下文,我正在尝试执行以下查询:

  var query = await(从上一个Context.ParentTable 
将孩子加入Context.ChildTable
on parent.ID equals child.ID
into allResult
from ResultValue in allResult.DefaultIfEmpty()
其中ResultValue.TenantId == tenantId
选择新的结果
{
代码= parent.Code,
Type = parent.Type,
ID = ResultValue == null?0:ResultValue.Id
})。ToListAsync();

我的单例上下文如下所示:

  public class BaseRepository 
{
private readonly IConfigurationContextFactory configurationContextFactory;

私人IConfigurationContext上下文;

protected IConfigurationContext上下文
{
get
{
return context? (context = configurationContextFactory.Context);
}
}

public BaseRepository(IConfigurationContextFactory configurationContextFactory)
{
this.configurationContextFactory = configurationContextFactory;
}
}

配置上下文工厂返回上下文,如下所示: p>

  private ConfigurationContext Get()
{
logger.WriteEntrySync(LogLevel.Information,
null! =上下文?配置上下文:使用现有上下文:配置上下文:Wiil创建新的上下文。
返回上下文? (context = new ConfigurationContext(connectionString));
}

在此我发现以下错误的间歇性问题:


在上一个
异步操作完成之前,第二个操作是在此上下文中开始的。使用'等待'来确保任何
异步操作已经完成,然后在此上下文调用另一个方法
之前。任何实例成员不能保证线程
安全。



解决方案


我有单身语境


这是你的问题。 DbContext 不是线程安全的,并且旨在一次执行一个查询。由于您正在共享您的 DbContext ,您可能会尝试同时调用另一个查询,这在 DbContext 条款。



您甚至可以在 TolistAsync 的标记:


不支持在同一上下文
实例上执行多个活动操作。使用'等待'来确保任何
异步操作已完成,然后再调用另一个方法
就可以了。


不要重复使用您的上下文与全局单例,每当您想查询数据库时创建一个新的上下文



编辑



而不是通过工厂方法获取单个上下文只需为每个查询分配一个新的值:

  using(var context = new ConfigurationContext(connectionString))
{
var query = await(来自context.Features中的功能
在context.FeatureFlags
中加入feature.FeatureId等于featureFlag.FeatureId
into allFeatures
from featureFlagValue in allFeatures.DefaultIfEmpty()
其中featureFlagValue.TenantId == tenantId
选择新的Bu sinessEntities.FeatureFlag
{
代码= feature.Code,
Type = feature.Type,
FeatureFlagId = featureFlagValue == null? 0:featureFlagValue.FeatureFlagId
})。ToListAsync();
}


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.

解决方案

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();
}

这篇关于实体框架异步问题上下文或查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆