«Лямбда-выражение с телом оператора не может быть преобразовано в дерево выражений» - PullRequest
148 голосов
/ 03 марта 2011

При использовании 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();

Я не знаю, что означает ошибка, ибольше всего как это исправить.Любая помощь?

Ответы [ 9 ]

97 голосов
/ 03 марта 2011

Является ли objects контекстом базы данных Linq-To-SQL?В этом случае вы можете использовать только простые выражения справа от оператора =>.Причина в том, что эти выражения не выполняются, а преобразуются в SQL для выполнения в базе данных.Попробуйте это

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar,
    Var2 = o.var2 
}).ToArray();
90 голосов
/ 23 февраля 2013

Вы можете использовать тело оператора в выражении lamba для IEnumerable коллекций.попробуйте это:

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

    return new Obj() 
    { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    };
}).ToArray();

Примечание:
Тщательно продумайте этот метод, потому что таким образом вы получите все результаты запроса в памяти, которые могут иметь нежелательные побочные эффектына остальной части вашего кода.

36 голосов
/ 03 марта 2011

Это означает, что вы не можете использовать лямбда-выражения с «телом оператора» (т. Е. Лямбда-выражениями, использующими фигурные скобки) в тех местах, где лямбда-выражения необходимо преобразовать в дерево выражений (например, в случае, когдаиспользуя linq2sql).

5 голосов
/ 03 марта 2011

Не зная больше о том, что вы делаете (Linq2Objects, Linq2Entities, Linq2Sql?), Это должно заставить его работать:

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

    return new Obj() { 
        Var1 = someLocalVar,
        Var2 = o.var2 
    }; 
}).ToArray();
3 голосов
/ 21 апреля 2013

Используйте эту перегрузку выбора:

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

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
})).ToArray();
1 голос
/ 01 ноября 2016

Объект возврата LINQ to SQL реализовывал интерфейс IQueryable.Таким образом, для параметра-предиката Select необходимо указывать только одно лямбда-выражение без тела.

Это связано с тем, что LINQ для кода SQL не выполняется внутри программы, а не на удаленной стороне, такой как SQL-сервер или другие.Этот тип выполнения отложенной загрузки был достигнут благодаря реализации IQueryable, где его ожидаемый делегат переносится в класс типов Expression, как показано ниже.

Expression<Func<TParam,TResult>>

Дерево выражений не поддерживает лямбда-выражения с телом и поддерживает только однострочное лямбда-выражениекак var id = cols.Select( col => col.id );

Так что, если вы попытаетесь, следующий код не будет работать.

Expression<Func<int,int>> function = x => {
    return x * 2;
}

Следующее будет работать в соответствии с ожиданиями.

Expression<Func<int,int>> function = x => x * 2;
1 голос
/ 03 марта 2011

Это означает, что лямбда-выражение типа TDelegate, содержащее ([parameters]) => { some code };, не может быть преобразовано в Expression<TDelegate>. Это правило.

Упростите ваш запрос. Тот, который вы указали, может быть переписан следующим образом и будет скомпилирован:

Arr[] myArray = objects.Select(o => new Obj()
                {
                   Var1 = o.someVar,
                   Var2 = o.var2
                } ).ToArray();
0 голосов
/ 27 октября 2015

Для вашего конкретного случая тело предназначено для создания переменной, и переключение на IEnumerable заставит все операции обрабатываться на стороне клиента, я предлагаю следующее решение.

Obj[] myArray = objects
.Select(o => new
{
    SomeLocalVar = o.someVar, // You can even use any LINQ statement here
    Info = o,
}).Select(o => new Obj()
{
    Var1 = o.SomeLocalVar,
    Var2 = o.Info.var2,
    Var3 = o.SomeLocalVar.SubValue1,
    Var4 = o.SomeLocalVar.SubValue2,
}).ToArray();

Редактировать: Переименовать для C # Coding Convention

0 голосов
/ 03 марта 2011

Является ли Arr базовым типом Obj?Существует ли класс Obj?Ваш код будет работать, только если Arr является базовым типом Obj.Вы можете попробовать это вместо:

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

    return new Obj() 
    { 
       Var1 = someLocalVar,
       Var2 = o.var2 
    };
}).ToArray();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...