LINQ contains exactly matching
LINQ contains exactly matching
We have the following class structure and want to query all user who has at least all roles or more from the mustHaveRole Queryparameter.
If someone has a good idea that would be cool :-)
public class User
{
public Guid UserId { get; set; }
public string Username { get; set; }
public ICollection<UserRole> Roles { get; set; } = new HashSet<UserRole>();
}
public class UserRole
{
public virtual User User { get; set; }
public Guid UserId { get; set; }
public virtual Role Role { get; set; }
public Guid RoleId { get; set; }
}
public class Role
{
public Guid RoleId { get; set; }
public string RoleName { get; set; }
public ICollection<User> Users { get; set; } = new HashSet<User>();
}
public class QueryHandler
{
readonly List<User> Users = new List<User>();
public IEnumerable<User> Handle(List<Guid> musthaveRoles)
{
var queryResult =
from u in Users
from r in u.Roles
where musthaveRoles.Contains(r.RoleId) //ContainsAllExact and not has one of the roles???
select u;
return queryResult;
}
}
2 Answers
2
If you need an exact match you can use SequenceEqual
method. To make it work you need to order your ids
SequenceEqual
ids
public IEnumerable<User> Handle(List<Guid> musthaveRoles)
{
var queryResult = Users.Where(
u => u.Roles.Select(r => r.RoleId).OrderBy(id => id)
.SequenceEqual(musthaveRoles.OrderBy(id => id)));
return queryResult;
}
This query will return only users who have exact same roles you expect and will filter out users who have more roles
the users with more roles should be also in the queryResult
You can use Intersect
method:
Intersect
public IEnumerable<User> Handle(List<Guid> musthaveRoles)
{
var queryResult = Users.Where(u => u.Roles.Select(r => r.RoleId)
.Intersect(musthaveRoles).Count() == musthaveRoles.Count);
return queryResult;
}
Check a demo
I extended the userobject with a collection of status. In the many to many relation they have a status value. my question is: how can we filter the users with the queried status and a minimum statusvalue. demo dotnetfiddle.net/CCVwEP
– Jorgenson
Jun 30 at 12:21
@Jorgenson it would be better if you create a new question for this. You can link this question with a new one or just copy example from net fiddle into new question
– Aleks Andreev
Jun 30 at 12:32
I think what you are looking for is this:
var queryResult = Users.Where(x => musthaveRoles.All(y => x.Roles.Select(z => z.RoleId).Contains(y)));
// or this way
var queryResult1 = Users.Where(x => !musthaveRoles.Except(x.Roles.Select(y => y.RoleId)).Any());
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
cool, but the users with more roles should be also in the queryResult
– Jorgenson
Jun 30 at 8:10