【问题标题】:Based on a Linq join I get the error A second operation started on this context before a previous operation completed基于 Linq 连接,我收到错误 A second operation started on this context before a previous operation completed
【发布时间】:2019-12-30 16:20:24
【问题描述】:

以下代码使用 dbcontext。

var CurrentUser = await userManager.GetUserAsync(User);
var DefaultLanguageID = CurrentUser.DefaultLangauge;

var TestForNull = (from c in _classificationLevel.GetAllClassificationLevels()
  join l in _classificationLevelLanguage.GetAllClassificationLevelLanguages()
  on c.Id equals l.ClassificationLevelId
  where c.ClassificationId == NewLevel.SuObject.ObjectId
  && l.LanguageId == DefaultLanguageID
  select c.Sequence).Count();

运行时出现错误

A second operation started on this context before a previous operation completed.

我不知道为什么。我可以想象第一个操作是: userManager.GetUserAsync(User);

并且在下一次启动时仍在运行。虽然前面有关键字 await。

我认为的另一个选项是在查询中检索两个表,并且它用于相同的 dbcontext。 1. _classificationLevel.GetAllClassificationLevels() 2. _classificationLevelLanguage.GetAllClassificationLevelLanguages()

这是错误的原因吗?

这些背后的方法是:

public IEnumerable<SuClassificationLevelModel> GetAllClassificationLevels()
{
    return context.dbClassificationLevel.AsNoTracking();
}

public IEnumerable<SuClassificationLevelLanguageModel> GetAllClassificationLevelLanguages()
{
    return context.dbClassificationLevelLanguage;
}

我没有异步/等待这些。我应该这样做吗?如果是,我应该怎么做?

在模型层面,两个模型是相关的,如下代码所示:

public interface IClassificationAndStatusRepository
{
    IEnumerable<SuObjectVM> GetAllClassifications();
    IEnumerable<SuClassificationStatusModel> GetAllStatus();
}

【问题讨论】:

  • 你需要对 userManager.GetUserAsync 的调用是异步的吗?如果你用 await 来做,你会得到同样的错误吗?
  • 我用 await 做到了,然后我得到了错误。该错误实际上发生在 TestForNull 代码行上。那么问题是,错误所说的两个操作是什么。其中之一是关于用户管理器的上一行吗?或者这两个操作都在 TestForNull 行中?
  • 糟糕。在我的评论中打错字。如果你没有等待,你会得到同样的错误吗?
  • (旁注... C# 命名约定将规定本地声明的变量以小写字母开头。这使得它们在重用时更容易被发现,并使它们在视觉上与类名和系统变量分开。所以var CurrentUser = 应该是var currentUser = 。同样的机智DefaultLanguageID
  • 如果我离开等待,那么我在 DefaultLangauge 的第二行(摆动的红线)上得到一个错误。而不是 GetUserAsync,我没有看到不是异步的替代方案。顺便说一句,我将尝试改进约定(对所有人来说仍然是新事物)。

标签: asp.net asp.net-mvc entity-framework linq asp.net-core


【解决方案1】:

您必须等待所有后续步骤才能正确使用 aync/await 结构。

您可以在您的情况下使用 CountAsync() 但异步计数只是 IQueryable 的扩展,因此您可能需要更改方法返回类型 IQueryable ,这样更快更安全

    public IQueryable<SuClassificationLevelModel> GetAllClassificationLevels()
    {
        return context.dbClassificationLevel;
    }

    public IQueryable<SuClassificationLevelLanguageModel> GetAllClassificationLevelLanguages()
    {
        return context.dbClassificationLevelLanguage;
    }

var currentUser = await userManager.GetUserAsync(User);
var defaultLanguageID = currentUser.DefaultLangauge;
var testForNull = await (from c in GetAllClassificationLevels()
                                 join l in GetAllClassificationLevelLanguages()
                                on c.Id equals l.ClassificationLevelId
                               where c.ClassificationId == NewLevel.SuObject.ObjectId
                               && l.LanguageId == defaultLanguageID
                                     select c.EmployeeID).CountAsync();

【讨论】:

    【解决方案2】:

    代码调用了2次同一个模型:

    var testForNull = await (from c in GetAllClassificationLevels()
                                     join l in GetAllClassificationLevelLanguages()
                                    on c.Id equals l.ClassificationLevelId
                                   where c.ClassificationId == NewLevel.SuObject.ObjectId
                                   && l.LanguageId == defaultLanguageID
                                         select c.EmployeeID).CountAsync();
    

    GetAllClassificationLevelLanguages() 和 GetAllClassificationLevels() 已经包含外键表。因此两者都调用相同的 2 个表。

    【讨论】:

    • 这是答案吗?
    猜你喜欢
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2021-05-08
    相关资源
    最近更新 更多