• Status: Solved
  • Priority: Medium
  • Security: Private
  • Views: 80
  • Last Modified:

Anyway to have 2 "contains" in this LINQ?

This line of code gets all the users with RoleId of 1.

I want to get all the users with all the roles (RoleId =1, RoleId =2,etc)

Anyway to do this with LINQ?

 
var users = _dataContext.Users.Where(x => x.Roles.Select(y => y.RoleId).Contains("1")).ToList();

Open in new window

0
Camillia
Asked:
Camillia
  • 11
  • 7
  • 2
  • +2
2 Solutions
 
FarWestCommented:
use this sample
List<string> cities = new List<string>() {"London", "Vancouver", "San Francisco"};

var cutomers = from c in Customers
        where cities.Contains(c.City)
        select c;

from
https://social.msdn.microsoft.com/Forums/en-US/47acd270-b097-4d5e-bfd1-4be25f7a0713/how-to-use-in-clause-in-linq?forum=linqtosql
0
 
it_saigeDeveloperCommented:
Perhaps something like:
using System;
using System.Collections.Generic;
using System.Linq;

namespace EE_Q28568474
{
	class Data
	{
		public string RoleID { get; set; }
	}

	class Program
	{
		readonly static List<Data> @set = new List<Data>()
		{ 
			new Data() { RoleID = "Role1"},
			new Data() { RoleID = "Role2"}
		};

		static void Main(string[] args)
		{
			var methodbased = @set.Where(x => x.RoleID.Contains("1") || x.RoleID.Contains("2")).Select(x => x.RoleID);
			var expressionbased = (from data in @set where data.RoleID.Contains("1") || data.RoleID.Contains("2") select data.RoleID);

			Console.WriteLine("Method based...");
			foreach (var item in methodbased)
				Console.WriteLine(item);

			Console.WriteLine("Expression based...");
			foreach (var item in expressionbased)
				Console.WriteLine(item);
			Console.ReadLine();
		}
	}
}

Open in new window


Produces the following output:Capture.JPG
-saige-
0
 
CamilliaAuthor Commented:
Ah, I have to actually name the roles. For example, if someone down the road adds another role, I have to change the code.

There's no such thing as "get ALL the roles" without naming them, looks like it.
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

 
Richard LeeSoftware EnthusiastCommented:
Hi Camilla,

You should check out the AccountController methods where you should find a lot of methods that suit your needs.

context.Roles.Select(r => r.Name)

Open in new window

0
 
it_saigeDeveloperCommented:
Not really name (so to speak) but if you are wanting to get multiple integer values you either convert the integer to a string and then use String.Contains or select the values where the value matches a comparer, e.g. -
using System;
using System.Collections.Generic;
using System.Linq;

namespace EE_Q28568474
{
	class Data
	{
		public int RoleID { get; set; }
		public string Name { get; set; }
	}

	class Program
	{
		readonly static List<Data> @set = new List<Data>()
		{ 
			new Data() { RoleID = 1, Name = "Role1"},
			new Data() { RoleID = 2, Name = "Role2"},
			new Data() { RoleID = 3, Name = "Role3"},
			new Data() { RoleID = 31, Name = "Role31"},
		};

		static void Main(string[] args)
		{
			var MethodBaseIntEquals = @set.Where(x => x.RoleID.Equals(1) || x.RoleID.Equals(2)).Select(x => x.RoleID);
			var ExpressionBasedIntEquals = (from data in @set where data.RoleID.Equals(1) || data.RoleID.Equals(2) select data.RoleID);
			var MethodBaseStringContains = @set.Where(x => x.RoleID.ToString().Contains("1") || x.RoleID.ToString().Contains("2")).Select(x => x.RoleID);
			var ExpressionBasedStringContains = (from data in @set where data.RoleID.ToString().Contains("1") || data.RoleID.ToString().Contains("2") select data.RoleID);

			Console.WriteLine("Method based int equals...");
			foreach (var item in MethodBaseIntEquals)
				Console.WriteLine(item);

			Console.WriteLine();
			Console.WriteLine("Expression based int equals...");
			foreach (var item in ExpressionBasedIntEquals)
				Console.WriteLine(item);

			Console.WriteLine();
			Console.WriteLine("Method based string contains...");
			foreach (var item in MethodBaseStringContains)
				Console.WriteLine(item);

			Console.WriteLine();
			Console.WriteLine("Expression based string contains...");
			foreach (var item in ExpressionBasedStringContains)
				Console.WriteLine(item);
			Console.ReadLine();
		}
	}
}

Open in new window


Produces the following output:Capture.JPG
As to why your initial solution is not working, it is because you are using Enumerable.Contains, which is used to tell if an Enumerable contains a value and not used to select a value as part of a linq statement.

-saige-
0
 
CamilliaAuthor Commented:
Thanks, i'll take a look
0
 
louisfrCommented:
If the list of Roles is in _dataContext.Roles, you can use
var users = _dataContext.Users.Where(x => ! _dataContext.Roles.Select(y => y.RoleId).Except(x.Roles.Select(y => y.RoleId)).Any()).ToList()

Open in new window

0
 
CamilliaAuthor Commented:
I'll try it, thanks
0
 
CamilliaAuthor Commented:
I turned on Profiler and that LINQ comes out as this and doesn't bring back any rows --> louisfr

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Email] AS [Email], 
    [Extent1].[EmailConfirmed] AS [EmailConfirmed], 
    [Extent1].[PasswordHash] AS [PasswordHash], 
    [Extent1].[SecurityStamp] AS [SecurityStamp], 
    [Extent1].[PhoneNumber] AS [PhoneNumber], 
    [Extent1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed], 
    [Extent1].[TwoFactorEnabled] AS [TwoFactorEnabled], 
    [Extent1].[LockoutEndDateUtc] AS [LockoutEndDateUtc], 
    [Extent1].[LockoutEnabled] AS [LockoutEnabled], 
    [Extent1].[AccessFailedCount] AS [AccessFailedCount], 
    [Extent1].[UserName] AS [UserName]
    FROM [dbo].[AspNetUsers] AS [Extent1]
    WHERE  NOT EXISTS (SELECT 
        1 AS [C1]
        FROM  (SELECT 
            [Extent2].[Id] AS [Id]
            FROM [dbo].[AspNetRoles] AS [Extent2]
        EXCEPT
            SELECT 
            [Extent3].[RoleId] AS [RoleId]
            FROM [dbo].[AspNetUserRoles] AS [Extent3]
            WHERE [Extent1].[Id] = [Extent3].[UserId]) AS [Except1]
    )

Open in new window

0
 
louisfrCommented:
If it brings no rows, maybe it means there are no users with all the roles.
0
 
CamilliaAuthor Commented:
I have one user with one role.
One user with no role.

It's ok if we can't figure it out. I can do it in a stored proc.
0
 
louisfrCommented:
How many roles is there?
0
 
CamilliaAuthor Commented:
2 roles. But users belong to one role. They can't be in 2 roles.
0
 
louisfrCommented:
I quote: "I want to get all the users with all the roles"
If no user can have all the roles, then you won't get any user with all the roles.
0
 
louisfrCommented:
Do you want to get the users grouped by role?
0
 
CamilliaAuthor Commented:
>I quote: "I want to get all the users with all the roles"
If no user can have all the roles, then you won't get any user with all the roles.

Do you want to get the users grouped by role?

No, I dont need it grouped. Just a grid with a list of users and their roles.
If a user doesn't have a role, in SQL, it can still be brought back with a Left Join. The "role" column will have nothing in it. I think that can be done with LINQ as well. That's what I wanted to try to begin with...join Users and Roles objects together.
0
 
louisfrCommented:
The following returns a collection of objects with properties User and Role (which can be null).
var users = _dataContext.Users.Select(user => new { User = user, Role = _dataContext.Roles.SingleOrDefault(role => user.Roles.Contains(role.RoleId)) });

Open in new window

0
 
CamilliaAuthor Commented:
Thanks, Louisfr. I really appreciate it that you stayed with this ticket. Let me try it and will post back.
0
 
CamilliaAuthor Commented:
I get this error. There's no "role.RoleId". I see role.Name and role.Id.  Tried both but i get the same error.

(It's ok if we need to give up)
rolerror.png
0
 
louisfrCommented:
Not easy without the data definitions.

Instead of
user.Roles.Contains(role.RoleId)

Open in new window

you can try
user.Roles.Contains(role)

Open in new window

or
user.Roles.Any(userRole => userRole.RoleId == role.RoleId)

Open in new window

0
 
CamilliaAuthor Commented:
I'll try it, thanks
0
 
CamilliaAuthor Commented:
Just in case you're wondering, this one worked. Thank you so much for sticking with this question.
It gets all the user information..including role name and Id.

              var users = _dataContext.Users.Select(user => new { User = user, Role = _dataContext.Roles.FirstOrDefault(role => user.Roles.Any(userRole => userRole.RoleId == role.Id)) });

Open in new window

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 11
  • 7
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now