it-swarm.com.de

"Ein Lambda-Ausdruck mit einem Anweisungshauptteil kann nicht in einen Ausdrucksbaum umgewandelt werden."

Bei der Verwendung des EntityFramework erhalte ich die Fehlermeldung "A lambda expression with a statement body cannot be converted to an expression tree", wenn ich versuche, folgenden Code zu kompilieren:

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

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

Ich weiß nicht was der Fehler bedeutet und vor allem wie ich ihn beheben kann. Irgendeine Hilfe?

131
pistacchio

Ist objects ein Linq-To-SQL-Datenbankkontext? In diesem Fall können Sie nur einfache Ausdrücke rechts neben dem Operator => verwenden. Der Grund ist, dass diese Ausdrücke nicht ausgeführt werden, sondern in SQL konvertiert werden, um für die Datenbank ausgeführt zu werden

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

Sie können den Anweisungskörper in einem Lamba-Ausdruck für IEnumerable collection . Verwenden. Versuchen Sie Folgendes:

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

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

Beachten:
Denken Sie bei der Verwendung dieser Methode sorgfältig nach, denn auf diese Weise haben Sie alle Abfrageergebnisse im Speicher, die unerwünschte Nebeneffekte auf den restlichen Code haben können.

81
Amir Oveisi

Das bedeutet, dass Sie keine Lambda-Ausdrücke mit einem "Anweisungskörper" (dh Lambda-Ausdrücken, die geschweifte Klammern verwenden) an Stellen verwenden können, an denen der Lambda-Ausdruck in einen Ausdrucksbaum konvertiert werden muss (was beispielsweise bei der Verwendung von linq2sql der Fall ist) .

33
sepp2k

Ohne mehr darüber zu wissen, was Sie tun (Linq2Objects, Linq2Entities, Linq2Sql?), Sollte dies funktionieren:

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

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

Verwenden Sie diese Überladung von select:

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

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

Dies bedeutet, dass ein Lambda-Ausdruck vom Typ TDelegate, der einen ([parameters]) => { some code }; enthält, nicht in einen Expression<TDelegate> konvertiert werden kann. Das ist die Regel.

Vereinfachen Sie Ihre Anfrage. Das von Ihnen angegebene kann wie folgt umgeschrieben werden und wird kompiliert:

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

Ist Arr ein Basistyp von Obj? Gibt es die Obj-Klasse? Ihr Code funktioniert nur, wenn Arr ein Basistyp von Obj ist. Sie können dies stattdessen versuchen:

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

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

Das LINQ to SQL-Rückgabeobjekt implementierte die IQueryable-Schnittstelle. Daher sollten Sie für den Prädikatparameter Select nur einen einzelnen Lambda-Ausdruck ohne body angeben.

Dies liegt daran, dass LINQ für SQL-Code nicht innerhalb des Programms ausgeführt wird, sondern auf einer entfernten Seite wie dem SQL-Server oder anderen. Dieser Ausführungstyp für das verzögerte Laden wurde durch die Implementierung von IQueryable erreicht, bei der der erwartete Delegat in der Ausdruckstypklasse wie folgt eingeschlossen wird.

Expression<Func<TParam,TResult>>

Der Ausdrucksbaum unterstützt keinen Lambda-Ausdruck mit Körper und nur der einzeilige Lambda-Ausdruck wie var id = cols.Select( col => col.id );.

Wenn Sie also versuchen, funktioniert der folgende Code nicht.

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

Das Folgende wird wie erwartet funktionieren.

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

In Ihrem speziellen Fall dient der Rumpf dazu, eine Variable zu erstellen. Wenn Sie zu IEnumerable wechseln, werden alle Vorgänge erzwungen, die auf Clientseite verarbeitet werden müssen. Ich empfehle die folgende Lösung.

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

Bearbeiten: Umbenennen für C # -Coding Convention

0
Luke Vo