"具有语句主体的lambda表达式无法转换为表达式树"

pis*_*hio 160 c# linq linq-to-entities entity-framework

在使用EntityFramework时,我A lambda expression with a statement body cannot be converted to an expression tree在尝试编译以下代码时收到错误" ":

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() { 
    Var1 = someLocalVar,
    Var2 = o.var2 };
}).ToArray();
Run Code Online (Sandbox Code Playgroud)

我不知道错误意味着什么,最重要的是如何解决它.有帮助吗?

Tim*_*ers 102

objectsLinq-To-SQL数据库上下文?在这种情况下,您只能在=>运算符的右侧使用简单表达式.原因是,这些表达式不会被执行,而是转换为SQL以对数据库执行.试试这个

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar,
    Var2 = o.var2 
}).ToArray();
Run Code Online (Sandbox Code Playgroud)


Ami*_*isi 93

您可以在lamba表达式中为IEnumerable集合使用语句体.试试这个:

Obj[] myArray = objects.AsEnumerable().Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    };
}).ToArray();
Run Code Online (Sandbox Code Playgroud)

注意:
使用此方法时仔细考虑,因为这样,您将在内存中获得所有查询结果,这可能会对其余代码产生不必要的副作用.

  • 不,这不是真正的答案.它会使您的查询在客户端执行.有关详细信息,请参阅此问题:http://stackoverflow.com/questions/33375998/optimize-linq-to-sql-statement-that-has-foreign-key-access/33376119 (11认同)
  • 这是真正的解决方案,在某些情况下难以应用已接受的答案 (5认同)
  • +1我喜欢这个!添加`AsEnumerable()`让我的问题消失了! (4认同)
  • 虽然我同意你的意见,但OP表示他正在使用EntityFramework.大多数情况下,在使用EF时,您希望数据库端尽可能多地完成工作.如果你在答案中注明案例,那就太好了. (2认同)

sep*_*p2k 37

这意味着你不能在lambda表达式需要转换为表达式树的地方使用带有"语句体"的lambda表达式(即使用花括号的lambda表达式)(例如使用linq2sql时的情况) .

  • 你......稍微改写了这个错误.@Tim Rogers的回答要好得多 (30认同)
  • 用于定义"语句体"的+1. (6认同)
  • @vbullinger 你在某种程度上是对的,但在更一般的意义上(在 linq-to-sql 的上下文之外),这是一个更直接的答案。它帮助我解决了 AutoMapper 错误 (4认同)
  • vbullinger:不过,它确实帮助了我。 (2认同)

spe*_*der 6

在不了解您在做什么的情况下(Linq2Objects,Linq2Entities,Linq2Sql?),这应该可以使它工作:

Arr[] myArray = objects.AsEnumerable().Select(o => {
    var someLocalVar = o.someVar;

    return new Obj() { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    }; 
}).ToArray();
Run Code Online (Sandbox Code Playgroud)

  • 这将强制查询对象进行评估。 (11认同)
  • 不一定-谁知道“ o”有多大?当我们想要的是2时,它可能有50个属性。 (2认同)
  • 使用这种技术时,我喜欢在调用 `.AsEnumerable()` 之前选择将要使用的字段为匿名类型 (2认同)

Azr*_*mil 6

LINQ to SQL 返回对象正在实现IQueryable接口。因此,对于Select方法谓词参数,您应该只提供没有主体的单个 lambda 表达式。

这是因为 LINQ for SQL 代码不在程序内部执行,而不是在 SQL 服务器或其他远程端执行。这种延迟加载执行类型是通过实现 IQueryable 实现的,其中它的期望委托被包装在像下面这样的表达式类型类中。

Expression<Func<TParam,TResult>>
Run Code Online (Sandbox Code Playgroud)

表达式树不支持带正文的 lambda 表达式,它只支持单行 lambda 表达式,如 var id = cols.Select( col => col.id );

因此,如果您尝试以下代码将不起作用。

Expression<Func<int,int>> function = x => {
    return x * 2;
}
Run Code Online (Sandbox Code Playgroud)

以下将按预期工作。

Expression<Func<int,int>> function = x => x * 2;
Run Code Online (Sandbox Code Playgroud)


Moh*_*sen 5

使用这个选择的重载:

Obj[] myArray = objects.Select(new Func<Obj,Obj>( o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
})).ToArray();
Run Code Online (Sandbox Code Playgroud)

  • @parliament:为了防止将所有行加载到内存中,您应该使用 `Expression&lt;Func&lt;Obj,Obj&gt;&gt;`。 (2认同)

Mat*_*ger 5

参加聚会晚了 9 年,但对您的问题采用了不同的方法(没有人提到过?):

语句体可以正常Func<>工作,但不能与Expression<Func<>>. IQueryable.Select想要一个Expression<>,因为它们可以为实体框架翻译 -Func<>不能。

因此,您要么使用AsEnumerable并开始处理内存中的数据(不推荐,如果不是真的必要的话),要么继续使用IQueryable<>推荐的 。有一种叫法linq query可以让一些事情变得更容易:

IQueryable<Obj> result = from o in objects
                         let someLocalVar = o.someVar
                         select new Obj
                         {
                           Var1 = someLocalVar,
                           Var2 = o.var2
                         };
Run Code Online (Sandbox Code Playgroud)

withlet你可以定义一个变量并在select(or where,...) 中使用它- 你继续使用IQueryable直到你真的需要执行并获取对象。

之后你可以 Obj[] myArray = result.ToArray()

  • 我刚刚查了一下这个!希望当我看到一篇 9 年前的帖子“一个新答案已添加到此帖子中”时,你能看到我脸上的好奇心。哈哈哈,时机不错。 (2认同)

Ata*_*hev 1

是 的Arr基本类型Obj吗?Obj 类存在吗?仅当 Arr 是 Obj 的基本类型时,您的代码才有效。你可以尝试这个:

Obj[] myArray = objects.Select(o =>
{
    var someLocalVar = o.someVar;

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
}).ToArray();
Run Code Online (Sandbox Code Playgroud)