I have a Func<ProductItemVendor, bool>
stored in CompareProductItemVendorIds
. I would like to use that expression in a LINQ query.
It appears the following is legal:
var results =
Repository.Query<ProductItemVendor>().Where(CompareProductItemVendorIds);
However, the following is not legal:
var results = from v in Repository.Query<ProductItemVendor>()
where CompareProductItemVendorIds(v)
select v;
This code produces an error:
The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
Questions:
Why are these statements so different that my Func<>
is legal in one but not the other? I thought they both basically did the same thing.
How can I make this work? Do I have to explicity create my Func<>
as an Expression<Func<>>
instead?
Please see my related question at Using Expression<Func<>> in a LINQ Query.
in conclusion no, it won't return null since null can't say sequence contains no elements it will always say object reference not set to an instance of an object ;) Save this answer.
Language-Integrated Query (LINQ) is the name for a set of technologies based on the integration of query capabilities directly into the C# language. Traditionally, queries against data are expressed as simple strings without type checking at compile time or IntelliSense support.
LINQKit is a free set of extensions for LINQ to SQL and Entity Framework power users. It comprises the following: An extensible implementation of AsExpandable() A public expression visitor base class (ExpressionVisitor) PredicateBuilder.
LINQ to SQL was the first object-relational mapping technology released by Microsoft. It works well in basic scenarios and continues to be supported in Visual Studio, but it's no longer under active development.
There is big difference between Expression<Func<T,bool>>
and Func<T,bool>
. First one is an expression tree. You can think of it as description of code. Linq to Entities requires expression trees. Because it needs to build SQL query. So it needs description of code to translate same actions into SQL.
Second one, Func<T,bool>
is a simple method with specified signature. Nothing special here. Why its legal here:
Repository.Query<ProductItemVendor>().Where(CompareProductItemVendorIds);
It's simple. There are two Where
extension methods. One fore IQueryable<T>
, which expects expression tree (which will be translated into SQL query). And another is extension for IEnumerable<T>
which expects ordinal method for in-memory collection filtering (usual C# code). Thus you don't have expression tree, latter one is chosen. No SQL generated here. This is your case.
Now second query:
from v in Repository.Query<ProductItemVendor>()
where CompareProductItemVendorIds(v)
select v
Actually it's not same query. It's equivalent to
Repository.Query<ProductItemVendor>().Where(v => CompareProductItemVendorIds(v));
And here you have lambda expression, which can be converted into expression tree. And another Where
extension is used - one for IQueryable<T>
. So, Linq to Entities tries to convert this expression tree to SQL. But what it should convert? Yes, invocation of some in-memory method. And, of course, Linq to Entities fails to do that.
In order to make your query work, you should use Expression<Func<T,bool>>
. You can build it manually, or you can use lambda expression.
The reason your first version works is Linq is being too smart for it's own good. The equivalent of your first version is actually
IEnumerable<ProductItemVendor> temp = Repository.Query<ProductItemVendor>().AsEnumerable();
var results = temp.Where(CompareProductItemVendorIds);
So when you perform your query you are returning every row in your database then performing a Where
in memory on the local computer.
To get the Where clause to be performed on the database you must change the type of CompareProductItemVendorIds
to be Expression<Func<ProductItemVendor, bool>>
.
There is no way to "convert" from Func<TIn, TOut>
to Expression<Func<TIn. Tout>>
, you must rewrite your code to initially be a expression, you could then convert to Func<TIn, TOut>
by calling CompareProductItemVendorIds.Compile()
Expression<Func<ProductItemVendor, bool>> CompareProductItemVendorIds = //...
Func<ProductItemVendor, bool> CompareProductItemVendorIdsAsFunc = CompareProductItemVendorIds.Compile();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With