The following code:
model.Items = dbQuery.Select(c => new Item {
Total = c.Items.Count((Func<Item, bool>)(t => t.Amount.HasValue))
}).ToArray();
Throws the following exception:
Internal .NET Framework Data Provider error 1025.
However the exact code minus the cast works:
model.Items = dbQuery.Select(c => new Item {
Total = c.Items.Count(t => t.Amount.HasValue)
}).ToArray();
Note: dbQuery
is just an EF ObjectQuery
.
The expected type for Count()
is Func<Item, bool>
, and it's even verified by ReSharper that they're the same type by the fact that it grays the cast out, suggesting that it's not needed and they're functionally equivalent.
However, the exception proves that they are not, in fact, functionally equivalent.
Also, I did see this related question/answer, but Count()
(in this case, anyway) will not accept an Expression<Func<Item bool>>
, so that doesn't work for me.
You want to "store [the] expression in a variable, for reuse purposes, and pass that into Count()
". This is 100% possible if the Expression
can be translated to SQL. The problem here is that you're introducing something that can't be translated to SQL. The particular issue in this case is that the cast gets translated to an Expression.Convert
. Your types definitely aren't represented in SQL, so this won't be able to execute. Plug both into LINQPad and check out the IL to see the difference.
As the other related question/answer you linked to suggests, you need to pass your predicate as an Expression
rather than a Func
(how to do the work vs. pointing to a location in code that does the work). The problem, as you noted, is that the Count
method doesn't take an Expression
, but this is easily resolved by using AsQueryable()
which will give you the IQueryable
extension methods that take Expression
.
This should have no problems executing:
Expression<Func<Item,bool>> predicate = i => i.Amount.HasValue;
model.Items = dbQuery.Select(c => new Item {
Total = c.Items.AsQueryable().Count(predicate)
}).ToArray();
The problem is that the data provider is not able to turn that LINQ expression into a SQL statement. In the one that is not working, Count is being passed a delegate to a method. Think of it as passing a pointer to a method like:
private static bool MyFunction(Item item)
{
return item.Amount.HasValue;
}
Now, the problem is that data provider is not going to get into that method an try to figure out how to turn it into SQL.
The data provider is very capable of traversing expression trees to build up SQL, which is how the "minus cast" example works, and also the related answer linked in your post.
If you can update your post with what you are trying to accomplish, I may be able to help you out.
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