当前位置: 首页 > 知识库问答 >
问题:

实体框架异步问题上下文还是查询?

郭德惠
2023-03-14

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

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

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

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

配置上下文工厂返回如下上下文:

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

在这我得到间歇性问题与以下错误:

在上一个异步操作完成之前,在此上下文上启动了第二个操作。使用“await”确保在该上下文上调用另一个方法之前已完成任何异步操作。任何实例成员都不能保证线程安全。

共有2个答案

松刚豪
2023-03-14

DbContext应该为一个业务事务(工作单元)而存在,不能多也不能少。业务事务通常是请求、页面或表单。DbContext不是线程安全的,它保留一个内部实体缓存并跟踪更改,因此您不能在多个请求中共享它。

您确实需要阅读实体框架文档:使用DbContext。

我不会为每个存储库创建一个实例,因为一个业务事务可以操作多个存储库。

您可以在存储库中注入上下文:

public class BaseRepository
{
    private IConfigurationContext context;
    public BaseRepository(IConfigurationContext context)
    {
        this.context = context;
    }
    //...
}

更改您的工厂,以便每次都创建一个实例:

public interface IConfigurationContextFactory
{
    IConfigurationContext CreateContext();
}

// ...
public ConfigurationContext CreateContext()
{
    return new ConfigurationContext(connectionString);
}

然后配置依赖解析程序,以每工作单元注入一个IConfigurationContext。假设您正在开发一个ASP。NET应用程序使用unity。

container.RegisterType<IConfigurationContext>(
    //Instance per http request (unit of work)
    new PerRequestLifetimeManager(),
    //Create using factory
    new InjectionFactory(c => c.Resolve<IConfigurationContextFactory>.CreateContext()));

当需要时,不要忘记在业务事务结束时调用SaveChangesSync:操作成功,修改需要持久化。

吕灿
2023-03-14

我有单例语境

这是你的问题DbContext不是线程安全的,设计为一次执行一个查询。由于您正在共享您的数据库上下文,您可能试图同时调用另一个查询,这在数据库上下文中是不合法的。

您甚至可以在ToListAsync的备注中看到:

不支持在同一上下文实例上执行多个活动操作。使用“await”确保在该上下文上调用另一个方法之前已完成任何异步操作。

您应该做的是不要通过全局单例重复使用您的上下文,每次您想要查询数据库时都要创建一个新的上下文。

编辑:

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

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

 类似资料:
  • 这是我的代码: 但是当我从控制器调用函数时。它显示错误 在上一个异步操作完成之前,在此上下文上启动了第二个操作。使用“await”确保在该上下文上调用另一个方法之前已完成任何异步操作。任何实例成员都不能保证线程安全。 请帮我解决这个问题。

  • 我有一个表存储3K条记录, 我对实体框架和ORM是个新手,但我能理解出了问题。 运行此linq查询时: 我在mysql端得到以下查询: 执行此查询大约需要3.50秒。 说明此查询: 当我查询: 我只有0.01秒... 跑着再解释一遍我得到: 我不明白为什么会这样。 Entity Framework 4.3 MySQL Connector Net 6.5.4.0 tcms_articles: 那么为

  • 问题内容: 像其他几个人一样,我在序列化Entity Framework对象时遇到问题,因此我可以通过JSON格式的AJAX发送数据。 我有以下服务器端方法,我正在尝试通过jQuery使用AJAX进行调用 通过AJAX调用会导致此错误: 这是因为实体框架创建循环引用以保持所有对象相关并且可访问服务器端的方式。 我从(http://hellowebapps.com/2010-09-26/produc

  • 问题内容: 我正在将子系统从 NHibernate 移植到 Entity Framework, 并希望看到将以下查询移植到 EF 的最佳方法。 帐户余额类别为: 该表是: 示例数据是(使用数字ID可以更好地理解): 该 AccountBalanceByDate 实体持有某一天的账户余额。如果某天没有交易,则该天将没有 AccountBalanceByDate ,我们应该查看前几天以查看该帐户的余额

  • 我目前正在阅读Trevor Burnham的Async Javascript。到目前为止这是一本很棒的书。 他谈到这个片段和console.log在Safari和Chrome控制台中是“异步”的。不幸的是我无法复制这个。代码如下: 如果这是异步的,我会预期结果是books的结果。将console.log()放在事件队列中,直到所有代码执行完毕,然后运行它,它将具有bar属性。 虽然它是同步运行的,

  • 我试图查找一个JMS TopicConnectionFactory使用JNDI在WebSphere应用服务器。我已经在服务器中正确地完成了jndi设置。我已经在服务器中部署了我的应用程序。 我为发送方/接收方/监听器设计了3个java类。在服务器中部署WAR之后,我首先尝试将接收器代码作为独立的java应用程序运行。然而,它失败了,错误如下: 线程“main”javax中出现异常。命名。NoIni