skip to Main Content

I have a LINQ query like this:

var data = from user in _context.Users
           select new
           {
               UserId = user.Id,
               Username = user.UserName,
               RoleNames = (from userRole in _context.UserRoles
                            join role in _context.Roles on userRole.RoleId
                            equals role.Id
                            where userRole.UserId == user.Id
                            select role.Name).ToList()
           };

if (!string.IsNullOrEmpty(searchText))
    data = data.Where(x => x.Username.Contains(searchText) || x.RoleNames.Any(r => r.Contains(searchText)));

The result are something like this:

User Id | Username      | RoleNames
1       | Matt          | [User, Admin]
2       | Jennifer      | [User]
3       | John          | []

But the

x.RoleNames.Any(r => r.Contains(searchText))

is not working, it’s causing InvalidOperationException: The LINQ expression ‘…’ could not be translated.

I want to pass in a searchText to search for either "Username" and "RoleNames" columns.
E.g. if I pass in searchText = ‘Jen’ it will return User Id 2, and if I pass in searchText = ‘user’ it will return User Id 1 and 2.

Any help would be appreciated.

2

Answers


  1. This may not be the answer you want now but you’ll probably look back on this and see it as the right answer later.

    Your ORM (Probably Entity Framework) can’t translate your Linq Expressions into a query. If your project will have a small database and you don’t need your queries to perform well then, tweak your expression so that the ORM can generate a functioning, albeit sub-optimal, query.

    If data will be a significant part of your project then switch to a light ORM like Dapper and learn the query language of your database. Write optimal, parameterised queries in that query language and yield the long term benefits.

    Login or Signup to reply.
  2. While theoretically it is possible to translate this condition to the SQL, your EF Core version do not supports that. Consider to make filter before defining custom projection:

    var users = _context.Users.AsQueryable();
    
    if (!string.IsNullOrEmpty(searchText))
        users = users.Where(x => x.Username.Contains(searchText) || x.Roles.Any(r => r.Contains(searchText)));
    
    var data = 
        from user in users
        select new
        {
            UserId = user.Id,
            Username = user.UserName,
            RoleNames = (from userRole in _context.UserRoles
                        join role in _context.Roles on userRole.RoleId
                        equals role.Id
                        where userRole.UserId == user.Id
                        select role.Name).ToList()
        };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search