Search code examples
entity-framework-6asp.net-identity-2

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


I am getting

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

error intermittently in an MVC project that uses asp.net identity 2.1. Basically I have a base controller where every other controller derives from, and this controller has a property that returns an ApplicationUser. (The extended class of asp.net identity user). The base controller has the following. Note that UserManager is retrieved from the OwinContext (and yes, it is created by using

CreatePerOwinContext()

method, just like in the templates.

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

Then in my other controllers, I freely call this property to get a reference to the ApplicationUser, an example being as follows

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

This sometimes works, and sometimes it gives the error I mentioned. I am not calling an async operation in the property or the controller method. So I am puzzled. Any ideas?


Solution

  • I suspect this line:

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

    Here you do a request for ApplicationUser, then lazy-load Affiliations, then for every select in Affiliations you do a request for ApplicationUser again.

    Do local caching for the ApplicationUser to avoid multiple requests to DB where only one is required:

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