Подтвердить что ты не робот

"Лямбда-выражение с телом оператора не может быть преобразовано в дерево выражений"

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

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

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

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

Ответ 6

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

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

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

Ответ 7

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

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

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

Ответ 8

В вашем конкретном случае тело предназначено для создания переменной, и переход на 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();

Изменить: переименовать для конвенции кодирования С#

Ответ 9

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

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

Expression<Func<TParam,TResult>>

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

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

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

Следующее будет работать как ожидалось.

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