Select common value in navigation table using LINQ

2019-08-06 09:32发布

问题:

I have a table called InvestigatorGroup and a table called InvestigatorGroupUsers which is used to see what groups have what users. I am trying to get the common investigator group between two users

My query is as follows:

    public InvestigatorGroup GetCommonGroup(string userId, string investigatorUserId)
    {
        using (GameDbContext entityContext = new GameDbContext())
        {
            string[] ids = new[] { userId, investigatorUserId };

            return entityContext.InvestigatorGroups
                .Where(i => i.IsTrashed == false)
                .Include(i => i.InvestigatorGroupUsers)
                .Where(i => i.InvestigatorGroupUsers.Any(e => ids.Contains(e.UserId)))
                .OrderByDescending(i => i.InvestigatorGroupId)
                .GroupBy(i => i.InvestigatorGroupId)
                .Where(i => i.Count() > 1)
                .SelectMany(group => group).FirstOrDefault();
        }
    }

The entity InvestigatorGroup is as follows:

public class InvestigatorGroup : IIdentifiableEntity
{
    public InvestigatorGroup()
    {
        this.InvestigatorGroupGames = new HashSet<InvestigatorGroupGame>();
        this.InvestigatorGroupUsers = new HashSet<InvestigatorGroupUser>();
    }

    // Primary key
    public int InvestigatorGroupId { get; set; }
    public string InvestigatorGroupName { get; set; }
    public bool HasGameAssignment { get; set; }
    public string GroupRoleName { get; set; }
    public bool IsTrashed { get; set; }

    // Navigation property
    public virtual ICollection<InvestigatorGroupUser> InvestigatorGroupUsers { get; private set; }
    public virtual ICollection<InvestigatorGroupGame> InvestigatorGroupGames { get; private set; }


    public int EntityId
    {
        get { return InvestigatorGroupId; }
        set { InvestigatorGroupId = value; }
    }

}

The problem is that it keeps returning a value of 0. It doesn't see the shared group with a count of 2 between the two users.

I did a test to return the groups (I removed the count>1 condition) and it returned all the groups for both users not only the one they have in common

I believe the issue is with this line: .Where(i => i.InvestigatorGroupUsers.Any(e => ids.Contains(e.UserId))) Thanks for the help!

回答1:

I've resolved this by changing my query so that it searches for the rows containing one of the UserId's. Then it queries through those selected rows and selects the ones containing the other UserId (InvestigatorUserId). This way only the rows containing both are returned

My new code is as follows:

    public InvestigatorGroup GetCommonGroup(string userId, string investigatorUserId)
    {
        using (GameDbContext entityContext = new GameDbContext())
        {
            IEnumerable<InvestigatorGroup> userGroups = entityContext.InvestigatorGroups
                .Where(i => i.IsTrashed == false)
                .Include(i => i.InvestigatorGroupUsers)
                .Where(i => i.InvestigatorGroupUsers.Any(e => e.UserId.Contains(userId)))
                .OrderByDescending(i => i.InvestigatorGroupId);

            return userGroups.Where(i => i.InvestigatorGroupUsers.Any(e => e.UserId.Contains(investigatorUserId))).FirstOrDefault();

        }
    }