Reputation: 5424
I'm trying to use an Expression
inside of a LINQ
Select
. Here is an example of my code
Expression<Func<user, string>> expr = d => d.user.username;
Message.Select(b => new { name = b.user.Select(expr) });
Message is of type IEnumerable
, at runtime i'm getting the following error :
The exception message is ''System.Collections.Generic.List<W.Models.user>' does not contain a definition for 'Select'
How do I fix this?
Upvotes: 2
Views: 10335
Reputation: 3123
Please have a look at Why would you use Expression<Func<T>> rather than Func<T>?.
The accepted answer describes that Func<T>
is a delegate to a method that returns a T
. Expression<Func<T>>
however is actually a description of how that delegate can be evaluated. You can for example compile an expression into an actual delegate:
Expression<Func<int, bool>> expr = i => i < 5;
Func<int, bool> deleg = expr.Compile();
Console.WriteLine("deleg(4) = {0}", deleg(4));
You can even write:
Console.WriteLine("deleg(4) = {0}", expr.Compile()(4));
So if you really need an expression you need to compile it into the actual delegate otherwise use the delegate in the first place.
(BTW: Your code example won't compile since there is no Select
method for a List<user>
that takes an expression and also d => d.user.username
is probably wrong. Since d
is a user
it should be d => d.username
).
However linq to entities does not support delegate calls. Therefore you have to switch to linq to objects by adding AsEnumerable()
:
Expression<Func<user, string>> expr = d => d.username;
Func<user, string> func = expr.Compile();
var result = context.Message.AsEnumerable()
.Select(b => new { name = b.user.Select(func) });
Use linq to entities for accessing the data, simple ordering, filtering etc. This way it can optimize the queries for the database but then switch to linq to objects if you need more.
PS: The lambda d => d.username
is compiled into a delegate. If you explicitly put it into the expression b.user.Select(u => u.username)
it will work fine because now this also compiles into an expression that linq to entities can handle without calling a delegate.
Upvotes: 0
Reputation: 1062650
It sounds like you are missing a using System.Linq;
at the top of your code file. Note, though, that List<T>
is LINQ-to-Objects; lose the Expression
:
Func<user, string> expr = d => d.user.username;
Message.Select(b => new { name = b.user.Select(expr) });
Final thought; while the message about System.Collections.Generic.List<W.Models.user>
suggests a list, your code (b.User.Select
/ Message.Select
) suggests individual objects. This is ... confusing.
Upvotes: 6