在同步 asp.net 身份调用中先前的异步操作完成错误之前,第二个操作在此上下文中启动

A second operation started on this context before a previous asynchronous operation completed error in a synchronous asp.net identity call

我得到

"A second operation started on this context before a previous asynchronous operation completed"

使用 asp.net identity 2.1 的 MVC 项目间歇性出错。基本上我有一个基本控制器,每个其他控制器都派生自该控制器,并且该控制器有一个 returns ApplicationUser 属性。 (asp.net 身份用户的扩展 class。基本控制器具有以下内容。请注意,UserManager 是从 OwinContext 中检索的(是的,它是使用

创建的

CreatePerOwinContext()

方法,就像在模板中一样。

protected ApplicationUser ApplicationUser
    {
        get
        {
            var userId = User.Identity.GetUserId();
            var applicationUser = UserManager.FindById(userId);
            if (applicationUser == null)
            {
                return null;
            }
            return applicationUser;
        }
    }

protected ApplicationUserManager UserManager
    {
        get
        {
            return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        set
        {
            _userManager = value;
        }
    }

然后在我的其他控制器中,我随意调用这个属性来获取对ApplicationUser的引用,示例如下

public ActionResult Index()
    {
        if (Request.IsAuthenticated)
        {
            var model = new OrganizationListViewModel(false)
            {
                OrganizationDetailViewModels = ApplicationUser.Affiliations
                   .Select(e => new OrganizationDetailViewModel(
                                e.Organization, ApplicationUser)).ToList()
            };
            return View(model);
        }
        else
        {
            return RedirectToAction("Search", "Search", new { type = "organization" });
        }
    }

这有时有效,有时会出现我提到的错误。我没有在属性或控制器方法中调用异步操作。所以我很疑惑。有什么想法吗?

我怀疑这一行:

OrganizationDetailViewModels = ApplicationUser.Affiliations
               .Select(e => new OrganizationDetailViewModel(
                            e.Organization, ApplicationUser)).ToList()

这里你请求 ApplicationUser,然后延迟加载 Affiliations,然后对于 Affiliations 中的每个 select,你请求 ApplicationUser 再次。

ApplicationUser 进行本地缓存,以避免在只需要一个的情况下向数据库发出多个请求:

private ApplicationUser _cachedUser;
protected ApplicationUser ApplicationUser
{
    get
    {
        var userId = User.Identity.GetUserId();

        if (_cachedUser == null)
        {
            var applicationUser = UserManager.FindById(userId);
            return applicationUser;
        }
        return _cachedUser;
    }
}