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.
CodePudding user response:
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.
CodePudding user response:
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()
};