2011-03-03 19 views
106

En el uso de la ADO.NET Entity Framework, me sale el error "A lambda expression with a statement body cannot be converted to an expression tree" al intentar compilar el código siguiente:"Una expresión lambda con un cuerpo de la declaración no se puede convertir en un árbol de expresión"

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

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

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

+3

intente realizar la conversión a esta lista. objects.List(). Select (... –

Respuesta

0

¿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. Puede probar este lugar:

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

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

Sin saber más acerca de 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(); 
+8

Esto obliga a la evaluación a evaluar. – smartcaveman

+0

Sin embargo, en esta circunstancia está bien, porque él llama a ToArray() inmediatamente después de todos modos. – smartcaveman

+2

no necesariamente - quién sabe qué tan grande "o "es? podría tener 50 propiedades cuando todo lo que queremos es 2. – kdawg

27

Esto significa que no se puede utilice expresiones lambda con un "cuerpo de declaración" (es decir, expresiones lambda que utilizan 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).

+17

Usted ... reformuló ligeramente la error. La respuesta de @Tim Rogers fue mucho mejor – vbullinger

+4

+1 para definir lo que es un "cuerpo de declaración". – TomNysetvold

+1

@vbullinger tienes razón hasta cierto punto, pero en un sentido más general (fuera del contexto de linq-a-sql) esta es una respuesta más directa. Me ayudó con un error de AutoMapper – mlhDev

69

¿Es objects un contexto de base de datos de 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 este

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

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

Simplifique su consulta. El uno que ya ha proporcionado puede reescribirse como la siguiente y compilará:

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

Usted puede utilizar cuerpo de la declaración en la expresión lambda para IEnumerable colecciones. probar esto:

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

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

Aviso:
Piense con cuidado cuando se utiliza este método, porque de esta manera, usted tendrá toda resultado de la consulta en la memoria, que pueden tener efectos secundarios no deseados en el resto de su código .

+3

+1 ¡Me gusta! Agregar 'AsEnumerable()' enmascara mi problema ¡vaya! – Joel

+5

Thi s es la solución real, la respuesta aceptada es difícil de aplicar en algunos casos –

+8

No, esta no es la respuesta real. Haría que tu consulta se ejecutara en el lado del cliente. Consulte esta pregunta para obtener más información: http://stackoverflow.com/questions/33375998/optimize-linq-to-sql-statement-that-has-foreign-key-access/33376119 –

2

Uso esta sobrecarga de select:

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

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

Esto funciona para mí, pero cuando se utiliza con Entity Framework, ¿evitaría esta solución que dbcontext cargue primero todas las filas en la memoria, como AsEnumerable()? – parliament

+1

@parliament: para evitar cargar todas las filas en la memoria, debe usar 'Expression >'. – Mohsen

0

para su caso específico, el cuerpo es para la creación de una variable, y el cambio a IEnumerable obligará a todas las operaciones que se procesa 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: Cambiar el nombre para C# Codificación Convención

0

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

Esto se debe a que el código de LINQ para SQL no se ejecuta dentro del programa en lugar del 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>> 

árbol de expresión no son compatibles con la expresión lambda con el cuerpo y su única línea de apoyo expresión lambda como var id = cols.Select(col => col.id);

tanto, si intenta el código siguiente no funciona.

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

El siguiente funcionará según lo esperado.

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