Interrogare l'entità con LINQ usando Nome campo Dyanmic

c# dynamic-linq expression-trees lambda linq-to-entities

Domanda

Ho creato una schermata di ricerca dinamica in ASP.NET MVC. Ho recuperato i nomi dei campi dall'entità tramite la riflessione in modo da consentire all'utente di scegliere i campi su cui desidera eseguire la ricerca anziché visualizzare tutti i campi nella vista.

Quando il risultato della ricerca viene riportato al controller, ricevo un oggetto FormCollection contenente FieldName e Value. Non so quanti campi vengono cercati e FormCollection contiene solo campi che sono stati scelti dall'utente.

Voglio essere in grado di prendere ora il nome di quel campo e applicarlo alla mia istruzione LINQ quando interrogo il database per esempio:

public List<People> SearchPeople(Dictionary<string, string> fieldValueDictionary)
{
    List<People> searchResults = new List<People>();

    foreach (string key in fieldValueDictionary.Keys)
    {
         searchResults.Add(entities.People.Where(p => p.<use the key string as the fieldName> == fieldValueDictionary[key]));
    }

    return searchResults;
}

Dove ho "usare la stringa di chiavi come fieldName" sarebbe come p => p.FirstName == fieldValueDictionary [chiave] dove key = "FirstName". Ho provato e non sono riuscito a utilizzare Lambda Expression Trees e ho avuto un piccolo successo con Dynamic LINQ. L'unica altra alternativa è fare qualcosa come:

public List<People> SearchPeople(Dictionary<string, string> fieldValueDictionary)
{
    IQueryable<People> results = entities.People;

    foreach (string key in fieldValueDictionary.Keys)
    {
         switch (k)
         {
             case "FirstName": results = results.Where(entities.People.Where(p => p.FirstName == k);
             case "LastName": results = results.Where(entities.People.Where(p => p.LastName == k);
             // Repeat for all 26 fields in table
         }
    }

    return results.ToList<People>();
}

AGGIORNAMENTO : ho svolto ricerche su Lambda Expression Trees attraverso i seguenti post:

crea dinamicamente espressioni lambda + linq + OrderByDescending

Problema con il parametro Expression.Lambda ()

LINQ: passaggio dell'espressione lambda come parametro da eseguire e restituito dal metodo

Sono arrivato a ottenere un lambda per produrre quanto segue: "p => p.FirstName", ma non riesco a farlo funzionare in un dove. Eventuali suggerimenti? Il mio codice è qui sotto:

MemberInfo member = typeof(People).GetProperty("FirstName");
ParameterExpression cParam = Expression.Parameter(typeof(People), "p");    
Expression body = Expression.MakeMemberAccess(cParam, member);        

var lambda = Expression.Lambda(body, cParam);

Risposta accettata

Dopo molte prove ed errori e ricerche ho accidentalmente trovato un altro post SO che copre lo stesso problema:

InvalidOperationException: nessun metodo 'Where' sul tipo 'System.Linq.Queryable' è compatibile con gli argomenti forniti

Ecco il mio codice modificato che funziona:

        IQueryable query = entities.People;
        Type[] exprArgTypes = { query.ElementType };

        string propToWhere = "FirstName";            

        ParameterExpression p = Expression.Parameter(typeof(People), "p");
        MemberExpression member = Expression.PropertyOrField(p, propToWhere);
        LambdaExpression lambda = Expression.Lambda<Func<People, bool>>(Expression.Equal(member, Expression.Constant("Scott")), p);                            

        MethodCallExpression methodCall = Expression.Call(typeof(Queryable), "Where", exprArgTypes, query.Expression, lambda);

        IQueryable q = query.Provider.CreateQuery(methodCall);

Con alcune modifiche sperabilmente abbastanza facili, dovrei essere in grado di farlo funzionare con qualsiasi tipo.

Grazie ancora per le tue risposte Ani e John Bowen


Risposta popolare

Hai provato a ottenere il valore da PropertyInfo?

entities.People.Where(p => (p.GetType().GetProperty(key).GetValue(p, null) as string) == fieldValueDictionary[key])


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché