Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting LINQ expression throws "Internal .NET Framework Data Provider error 1025."

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.

like image 945
Jerad Rose Avatar asked Jul 15 '14 18:07

Jerad Rose


2 Answers

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();
like image 154
Ocelot20 Avatar answered Nov 04 '22 09:11

Ocelot20


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.

like image 22
Mike Hixson Avatar answered Nov 04 '22 09:11

Mike Hixson