以下代码:
model.Items = dbQuery.Select(c => new Item {
Total = c.Items.Count((Func<Item, bool>)(t => t.Amount.HasValue))
}).ToArray();
引发以下异常:
内部.NET Framework数据提供程序错误1025。
然而,确切的代码减去演员阵容:
model.Items = dbQuery.Select(c => new Item {
Total = c.Items.Count(t => t.Amount.HasValue)
}).ToArray();
注意:dbQuery
只是一个EF ObjectQuery
。
Count()
的预期类型是Func<Item, bool>
,它甚至被ReSharper证实,它们是相同的类型,因为它会抛弃掉,表明它不需要它们'在功能上等同。
然而,异常证明它们不,实际上在功能上是等效的。
此外,我确实看到this related question/answer,但Count()
(在这种情况下,无论如何)都不会接受Expression<Func<Item bool>>
,因此对我不起作用。
答案 0 :(得分:11)
您希望将[]表达式存储在变量中,以便重复使用,并将其传递给Count()
&#34;。如果Expression
可以转换为SQL,则这是100%可能的。这里的问题是您正在引入无法转换为SQL的内容。在这种情况下的特殊问题是演员表被转换为Expression.Convert
。您的类型肯定不会在SQL中表示,因此无法执行。将两者插入LINQPad并检查IL以查看差异。
正如您链接到的其他相关问题/答案建议的那样,您需要将谓词作为Expression
而不是Func
(如何)传递给作品vs指向执行工作的代码中的位置。正如您所指出的那样,问题是Count
方法不会使用Expression
,但使用AsQueryable()
可以很容易地解决这个问题,这会为您提供IQueryable
Expression
。
执行时应该没有问题:
Expression<Func<Item,bool>> predicate = i => i.Amount.HasValue;
model.Items = dbQuery.Select(c => new Item {
Total = c.Items.AsQueryable().Count(predicate)
}).ToArray();
答案 1 :(得分:1)
问题是数据提供程序无法将该LINQ表达式转换为SQL语句。在没有工作的那个中,Count被传递给一个方法的委托。可以把它想象为将指针传递给类似的方法:
private static bool MyFunction(Item item)
{
return item.Amount.HasValue;
}
现在,问题在于数据提供者不会试图弄清楚如何将其转换为SQL。
数据提供程序非常能够遍历表达式树来构建SQL,这就是“减去投射”示例的工作方式,以及您帖子中链接的相关答案。
如果您可以根据自己的目标更新帖子,我可能会帮助您。