expresiones expresion arboles c# linq entity-framework linq-to-entities

c# - arboles - "Una expresión lambda con un cuerpo de declaración no se puede convertir a un árbol de expresiones"



expresiones lambda c# pdf (9)

Al usar EntityFramework , aparece el error " A lambda expression with a statement body cannot be converted to an expression tree " cuando intento compilar el siguiente código:

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

No sé qué significa el error y, sobre todo, cómo solucionarlo. ¿Alguna ayuda?


¿ Arr es un tipo base de Obj ? ¿Existe la clase Obj? Su código solo funcionaría si Arr es un tipo base de Obj. Puedes probar esto en su lugar:

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


¿Los objects un contexto de base de datos Linq-To-SQL? En ese caso, solo puede usar expresiones simples a la derecha del operador =>. El motivo es que estas expresiones no se ejecutan, sino que se convierten en SQL para ejecutarse en la base de datos. Prueba esto

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


El objeto de retorno LINQ to SQL implementaba la interfaz IQueryable . Por lo tanto, para el parámetro de predicado Select método, solo debe proporcionar una expresión lambda única sin cuerpo.

Esto se debe a que LINQ para el código SQL no se ejecuta dentro del programa en lugar de en el lado remoto como el servidor SQL u otros. Este tipo de ejecución de carga diferida se logró mediante la implementación de IQueryable, donde su delegado esperado se ajusta a la clase de tipo de expresión, como se muestra a continuación.

Expression<Func<TParam,TResult>>

El árbol de expresiones no admite la expresión lambda con body y solo admite una sola línea de expresión lambda como var id = cols.Select( col => col.id );

Entonces, si prueba el siguiente código, no funcionará.

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

El siguiente funcionará según lo esperado.

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


Para su caso específico, el cuerpo es para crear una variable, y cambiar a IEnumerable obligará a todas las operaciones a procesarse en el lado del cliente, propongo la siguiente solución.

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();

Editar: Renombrar para C # Coding Convention


Puede usar cuerpo de declaración en la expresión lamba para colecciones IEnumerable . prueba este:

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

Darse cuenta:
Piense con cuidado cuando use este método, ya que de esta manera tendrá todos los resultados de la consulta en la memoria, que pueden tener efectos secundarios no deseados en el resto de su código.


Significa que no puede usar expresiones lambda con un "cuerpo de declaración" (es decir, expresiones lambda que usan llaves) en lugares donde la expresión lambda debe convertirse en un árbol de expresiones (que es por ejemplo el caso cuando se usa linq2sql) .


Significa que una expresión Lambda de tipo TDelegate que contiene a ([parameters]) => { some code }; no se puede convertir a Expression<TDelegate> . Es la regla.

Simplifica tu consulta. El que proporcionó puede reescribirse como el siguiente y se compilará:

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


Sin saber más sobre lo que está haciendo (Linq2Objects, Linq2Entities, Linq2Sql?), Esto debería hacer que funcione:

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


Use esta sobrecarga de seleccionar:

Obj[] myArray = objects.Select(new Func<Obj,Obj>( o => { var someLocalVar = o.someVar; return new Obj() { Var1 = someLocalVar, Var2 = o.var2 }; })).ToArray();