困惑过表达与函数功能参数 [英] Confused about passing Expression vs. Func arguments

查看:77
本文介绍了困惑过表达与函数功能参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些无法理解的表达和funcs中如何工作之间的差异。
这个问题打开了,当有人从改变方法签名:

I'm having some trouble understanding the differences between how Expressions and Funcs work. This problem turned up when someone changed a method signature from:

public static List<Thing> ThingList(Func<Thing, bool> aWhere)

public static List<Thing> ThingList(Expression<Func<Thing, bool>> aWhere)



这打破了我的调用代码。旧的调用代码(合作)是这样的:

Which broke my calling code. The old calling code (which worked) looked like this:

        ...
        object y = new object();
        Func<Thing, bool> whereFunc = (p) => p == y;
        things = ThingManager.ThingList(whereFunc);

新的代码(不工作)看起来是这样的:

The new code (which doesn't work) looks like this:

        ...
        object x = new object();
        Expression<Func<Thing, bool>> whereExpr = (p) => p == x;
        things = ThingManager.ThingList(whereExpr);

这对利用表达线路发生故障时内部ThingList(...):

This fails inside ThingList(...) on the line utilizing the expression:

        var query = (from t in context.Things.Where(aWhere)
        ...

通过运行时错误:

Unable to create a constant value of type 'System.Object'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

这例子是人为的,但我的猜测是它是与本地对象变量x没有被正确复制到表情。

This example is contrived, but my guess is it has something to do with the local object variable x not being properly "copied" into the expression.

有人能解释如何在一般处理这种情况,为什么Func键工作,但表达不?

Can someone explain how to handle this situation in general, and why the Func works but the Expression doesn't?

谢谢!

推荐答案

究其原因,变化几乎可以肯定是推的谓词的评价为基础店,它备份你的背景而是将所有的东西到内存中,然后使用 Func键<东西,BOOL> 来决定保留哪些,改变的API的作者决定使用的IQueryable ,并且需要一个表达式来; Func键<事,布尔>>

The reason for the change almost certainly was to "push" the evaluation of your predicate into the underlying store, which backs your context. Instead of bringing all Things into memory and then using Func<Thing,bool> to decide which ones to keep, the author of the changed API decided to use IQueryable, and needed an Expression<Func<Thing,bool>> for that.

您是在错误的起源正确的。不像在内存中的谓词,的IQueryable 不能使用它不知道对象,例如对象的任意实例。

You are correct on the origin of the error: unlike in-memory predicates, IQueryable cannot use objects that it does not know, e.g. arbitrary instances of object.

您需要做的是改变的表达,以避免引用的数据类型的对象不是你的目标数据存储支持(我假设表达最终使其进入任何一个实体框架或LINQ2SQL上下文)。例如,而不是说

What you need to do is to change the expression to avoid referencing objects of data types not supported by your target data store (I assume the expression eventually makes its way into either an Entity Framework or a Linq2Sql context). For example, instead of saying

object x = new object();
Expression<Func<Thing, bool>> whereExpr = (p) => p == x;
things = ThingManager.ThingList(whereExpr);



你应该说

you should say

Thing x = new Thing {id = 123};
Expression<Func<Thing, bool>> whereExpr = (p) => p.id == x.id;
things = ThingManager.ThingList(whereExpr);



(您的后备存储几乎可以肯定明白整数)

(your backing store almost certainly understands integers)

这篇关于困惑过表达与函数功能参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆