C# 铸造LINQ表达式抛出“;内部.NET Framework数据提供程序错误1025。”;

C# 铸造LINQ表达式抛出“;内部.NET Framework数据提供程序错误1025。”;,c#,linq,entity-framework,C#,Linq,Entity Framework,以下代码: model.Items = dbQuery.Select(c => new Item { Total = c.Items.Count((Func<Item, bool>)(t => t.Amount.HasValue)) }).ToArray(); 注意:dbQuery只是一个EFObjectQuery Count()的预期类型是Func,ReSharper甚至验证了它们是相同的类型,因为它使强制显示变灰,这表明不需要它,而且它们在功能上是等效的 然

以下代码:

model.Items = dbQuery.Select(c => new Item {
    Total = c.Items.Count((Func<Item, bool>)(t => t.Amount.HasValue))
}).ToArray();
注意:
dbQuery
只是一个EF
ObjectQuery

Count()
的预期类型是
Func
,ReSharper甚至验证了它们是相同的类型,因为它使强制显示变灰,这表明不需要它,而且它们在功能上是等效的

然而,这一例外证明,事实上,它们在功能上并不等同


另外,我确实看到了,但是
Count()
(无论如何,在本例中)将不接受
表达式,因此这对我不起作用。

问题是数据提供程序无法将该LINQ表达式转换为SQL语句。在不起作用的方法中,Count被传递一个委托给一个方法。可以将其视为向如下方法传递指针:

private static bool MyFunction(Item item)
{
    return item.Amount.HasValue; 
}
现在的问题是,数据提供程序不会进入该方法,也不会试图找出如何将其转换为SQL

数据提供程序非常能够遍历表达式树来构建SQL,这就是“减号转换”示例的工作方式,也是您文章中链接的相关答案

如果你能用你想完成的内容更新你的帖子,我也许能帮你。

你想“为了重用的目的,将表达式存储在变量中,并将其传递到
Count()
”。如果可以将
表达式
转换为SQL,则这是100%可能的。这里的问题是,您正在引入一些无法转换为SQL的东西。本例中的特殊问题是转换为
表达式。Convert
。您的类型肯定没有在SQL中表示,因此无法执行。将两者都插入LINQPad并检查IL以查看差异

正如链接到的另一个相关问题/答案所建议的那样,您需要将谓词作为
表达式传递,而不是
Func
(如何执行工作,而不是指向代码中执行工作的位置)。正如您所指出的,问题在于
Count
方法不采用
表达式
,但这可以通过使用
AsQueryable()
轻松解决,这将为您提供采用
表达式
IQueryable
扩展方法

这在执行以下操作时应该没有问题:

Expression<Func<Item,bool>> predicate = i => i.Amount.HasValue;

model.Items = dbQuery.Select(c => new Item {
    Total = c.Items.AsQueryable().Count(predicate)
}).ToArray();
表达式谓词=i=>i.Amount.HasValue;
model.Items=dbQuery.Select(c=>newitem{
总计=c.Items.AsQueryable().Count(谓词)
}).ToArray();

那么,为什么您试图添加一些设计为无用的东西,但这会导致您的代码根本无法工作呢。如果你那样做会受伤,不要那样做。你试着改用
Espression
吗?@AlexanderGalkin他在问题中回答得很对。@Servy为了简单起见,我试图从细节中抽象出实际问题。但归根结底,我试图在(更复杂的)表达式中重用逻辑,而将此逻辑存储在
Func
中是行不通的。但是如果我能让上面的代码正常工作,那么我就能解决更复杂的实际问题。@JeradRose不,你不能。您提供的代码在理论上是可以工作的,如果查询提供程序足够健壮,可以预期它。实际上,从表达式中提取代码并将其存储在委托中实际上会从表达式中删除信息,这使得查询提供程序无法访问信息,无论其编写得多么健壮。当然,这并不是说不可能将一个表达式拆分为多个表达式,因为将代码放入委托中是不可能的。非常好的解释,谢谢。你可能已经回答了我的问题:这是不可能的。基本上,我是在尝试做你说我做不到的事情:将我的表达式存储在一个变量中,以便重用,然后将其传递到
Count()
。实际上,它是一个表达式。它是一个表示委托创建的表达式,因此所有信息都在表达式中,理论上可以转换为SQL。查询提供程序根本不希望执行此特定操作,因此会出错,但这是因为他们不希望执行此操作并围绕此操作编写代码,而不是因为他们需要的信息不在那里。@JeradRose那么您正在执行问题中未显示的操作,因为在你的问题中,这根本不是你要做的。@Servy我明白你的意思,但无论我是将表达式拉出到变量中,还是简单地将表达式内联转换,我都会得到同样的例外。你确定迈克的建议不对吗?从理论上讲,你说的有道理(我也是这么想的)。但实际上,.NET似乎在某种程度上对强制转换和未强制转换表达式的处理有所不同。要存储的表达式有什么模式吗?例如,所有表达式都将计算某个属性(在运行时确定)是否可为null?非常确定查询提供程序不知道如何处理
AsQueryable
调用。我也不认为会,但它确实可以(至少在EF6->MSSQLS2008中)。这要归功于评论员对OP链接到的问题的公认答案。它生成了适当的SQL代码,而不仅仅是在应用程序端完成工作?是的,也证实了这一点。
Expression<Func<Item,bool>> predicate = i => i.Amount.HasValue;

model.Items = dbQuery.Select(c => new Item {
    Total = c.Items.AsQueryable().Count(predicate)
}).ToArray();