Générer des expressions de sélection lambda dynamiques

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

Question

Je suis un peu nouveau sur les arbres d'expression et je ne comprends tout simplement pas certaines choses.

Ce que je dois faire est d’envoyer une liste de valeurs et de sélectionner les colonnes d’une entité à partir de ces valeurs. Je ferais donc un appel quelque chose comme ceci:

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

Je veux que cela soit traduit en code comme ceci ( Contact est une entité utilisant EF4):

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

Alors disons que j'ai le code suivant:

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

Quand j'ai couru le code ci-dessus j'ai eu l'erreur suivante:

L'entité ou le type complexe 'Contact' ne peut pas être construit dans une requête LINQ to Entities.

J'ai regardé le corps de la requête et elle a émis le code suivant:

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

Je suis presque sûr que je devrais être capable de construire une nouvelle entité parce que j'ai écrit cette ligne explicitement comme test pour voir si cela pouvait être fait:

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

Cela a fonctionné, mais je dois construire le select de manière dynamique.

J'ai essayé de décompiler une requête simple (la première fois que j'ai examiné le code de bas niveau) et je ne parviens pas à le traduire correctement. Le code de haut niveau que j'ai entré est:

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

En changeant la structure utilisée dans le décompilateur, je reçois ce code:

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

J'ai cherché à comprendre cela à plusieurs endroits, mais je ne l'ai pas encore bien compris. Quelqu'un peut-il aider?

Ce sont quelques endroits que j'ai regardés:

Réponse populaire

Quand je l'avais fait la dernière fois, j'avais projeté le résultat dans une classe non mappée (pas une entité) et que cela fonctionnait, tout le reste était identique à celui de votre code. Etes-vous sûr que la requête dynamique comme .Select (i => nouveau contact {ID = i.ID, NAME = i.NAME}) fonctionne?



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow