Mukil Deepthi
Mukil Deepthi

Reputation: 6452

C# entity framework make second call to query database

I am trying to fetch each user's manager details. Here is my linq query. But getting the following error:

A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext, however, instance members are not guaranteed to be thread-safe

Main method:

public async Task<IList<SecurityAdminUser>> AllSecurityAdminUsers()
    {
        return await _context.User
            .AsNoTracking()
            .Where(u => !u.Disabled)
            .Select(u => MapToSecurityAdminUser(u, 0))
            .ToListAsync();
    }
    

Second method:

    private SecurityAdminUser MapToSecurityAdminUser(EntityUser u, int loopCount)
    {
        //Only return the first level
        if (loopCount > 1) return null; 

        return new SecurityAdminUser
        {
            UserGuid = u.UserGuid,
            AccountName = u.AccountName,
            FirstName = u.Forename,
            LastName = u.Surname,
            Email = u.Email,
            KnownAs = u.KnownAs,
            Disabled = u.Disabled,
            OriginalHireStartDate = u.OriginalHireStartDate,
            TerminationDate = u.TerminationDate,
            ManagerUser = u.ManagerId != null ? MapToSecurityAdminManagerUser(u, loopCount) : null
        };
    }

    private SecurityAdminUser MapToSecurityAdminManagerUser(EntityUser u, int loopCount)
    {

//Getting error here

        var managerUser = _context.User.Where(manager => manager.Id == u.ManagerId).FirstOrDefault();

        if (managerUser == null) return null;

        loopCount++;
        return MapToSecurityAdminUser(managerUser, loopCount);
    }   

Upvotes: 1

Views: 41

Answers (1)

mbj
mbj

Reputation: 1015

The error occurs because your MapToSecurityAdminManagerUser method, which tries to execute a new query, is called (via MapToSecurityAdminUser) from the Select expression used by the query in your main method.

The fastest way to fix your code would be to change the main method so that the mapping happens after the first query has finished, something like this:

public async Task<IList<SecurityAdminUser>> AllSecurityAdminUsers()
{
    var users = await _context.User
        .AsNoTracking()
        .Where(u => !u.Disabled)
        .ToListAsync();

    return users.Select(u => MapToSecurityAdminUser(u, 0)).ToList();
}

Upvotes: 1

Related Questions