Dynamische Auswahl von Lambda-Ausdrücken generieren

entity-framework expression-trees lambda linq-to-entities

Frage

Ich bin mit Ausdrucksbäumen etwas neu und ich verstehe einige Sachen einfach nicht.

Was ich tun muss, ist eine Liste von Werten zu senden und die Spalten für eine Entität aus diesen Werten auszuwählen. Also würde ich so etwas anrufen:

DATASTORE<Contact> dst = new DATASTORE<Contact>();//DATASTORE is implemented below.
List<string> lColumns = new List<string>() { "ID", "NAME" };//List of columns
dst.SelectColumns(lColumns);//Selection Command

Ich möchte, dass das in Code wie folgt übersetzt wird ( Contact ist eine Entität, die das EF4 verwendet):

Contact.Select(i => new Contact { ID = i.ID, NAME = i.NAME });

Also sagen wir, ich habe den folgenden Code:

public Class<t> DATASTORE where t : EntityObject
{
    public Expression<Func<t, t>> SelectColumns(List<string> columns)
    {
        ParameterExpression i = Expression.Parameter(typeof(t), "i");
        List<MemberBinding> bindings = new List<MemberBinding>();

        foreach (PropertyInfo propinfo in typeof(t).GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (columns.Contains(propinfo.Name))
            {
                MemberBinding binding = Expression.Bind(propinfo, Expression.Property(i, propinfo.Name));
                bindings.Add(binding);
            }
        }

        Expression expMemberInit = Expression.MemberInit(Expression.New(typeof(t)), bindings);
        return Expression.Lambda<Func<t, t>>(expMemberInit, i);
    }

Wenn ich den obigen Code ausgeführt habe, habe ich den folgenden Fehler erhalten:

Die Entität oder der komplexe Typ 'Contact' kann nicht in einer LINQ to Entities-Abfrage erstellt werden.

Ich habe den Hauptteil der Abfrage betrachtet und folgenden Code ausgegeben:

{i => new Contact() {ID = i.ID, NAME = i.NAME}}

Ich bin mir ziemlich sicher, dass ich in der Lage sein sollte, eine neue Entität zu konstruieren, weil ich diese Zeile explizit als Test geschrieben habe, um zu sehen, ob dies möglich ist:

.Select(i => new Contact{ ID = i.ID, NAME = i.NAME })

Das hat funktioniert, aber ich muss das select dynamisch aufbauen.

Ich habe versucht, eine direkte Abfrage zu dekompilieren (das erste Mal, dass ich den Low-Level-Code angeschaut habe) und ich kann es nicht übersetzen. Der von mir eingegebene High-Level-Code ist:

Expression<Func<Contact, Contact>> expression = z => 
                    new Contact { ID = z.ID, NAME = z.NAME };

Ich ändere das im Decompiler verwendete Framework:

ParameterExpression expression2;
Expression<Func<Contact, Contact>> expression = 
   Expression.Lambda<Func<Contact, Contact>>
      (Expression.MemberInit(Expression.New((ConstructorInfo) methodof(Contact..ctor),
         new Expression[0]), new MemberBinding[] { Expression.Bind((MethodInfo) 
            methodof(Contact.set_ID), Expression.Property(expression2 = Expression.Parameter(typeof(Contact), "z"), (MethodInfo) 
            methodof(Contact.get_ID))), Expression.Bind((MethodInfo) 
            methodof(Contact.set_NAME), Expression.Property(expression2, (MethodInfo) 
               methodof(Contact.get_NAME))) }), new ParameterExpression[] { expression2 
        });

Ich habe verschiedene Orte gesucht, um das zu verstehen, aber ich habe es noch nicht verstanden. Kann jemand helfen?

Dies sind einige Orte, die ich gesucht habe:

Beliebte Antwort

Als ich es das letzte Mal gemacht habe, projizierte ich das Ergebnis auf die nicht gemappte Klasse (nicht auf die Entity) und es funktionierte, alles andere war genauso wie in deinem Code. Sind Sie sicher, dass keine dynamische Abfrage wie .Select (i => neuer Kontakt {ID = i.ID, NAME = i.NAME}) funktioniert?



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum