Sono un po 'nuovo per gli alberi di espressione e non capisco proprio alcune cose.
Quello che devo fare è inviare un elenco di valori e selezionare le colonne per un'entità da quei valori. Quindi farei una chiamata come questa:
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
Voglio che questo sia tradotto in codice come questo ( Contact
è un'entità che usa l'EF4):
Contact.Select(i => new Contact { ID = i.ID, NAME = i.NAME });
Quindi diciamo che ho il seguente codice:
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);
}
Quando ho eseguito il codice sopra ho ricevuto il seguente errore:
L'entità o il tipo complesso "Contatto" non può essere costruito in una query LINQ to Entities.
Ho esaminato il corpo della query e ha emesso il seguente codice:
{i => new Contact() {ID = i.ID, NAME = i.NAME}}
Sono abbastanza sicuro che dovrei essere in grado di costruire una nuova entità perché ho scritto questa linea esplicitamente come test per vedere se questo potrebbe essere fatto:
.Select(i => new Contact{ ID = i.ID, NAME = i.NAME })
Questo ha funzionato, ma ho bisogno di costruire la selezione in modo dinamico.
Ho provato a decompilare una query diretta (la prima volta che ho visto il codice di basso livello) e non riesco a tradurlo. Il codice di alto livello che ho inserito è:
Expression<Func<Contact, Contact>> expression = z =>
new Contact { ID = z.ID, NAME = z.NAME };
Cambiando il framework usato nel decompilatore ottengo questo codice:
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
});
Ho cercato diversi posti per cercare di capire questo, ma non l'ho ancora ottenuto. Qualcuno può aiutare?
Questi sono alcuni posti che ho visto:
Quando l'ho fatto l'ultima volta ho proiettato il risultato su una classe non mappata (non sull'entità) e ha funzionato, tutto il resto era lo stesso del tuo codice. Sei sicuro che la query non dinamica come .Select (i => new Contact {ID = i.ID, NAME = i.NAME}) funziona?