Interrogation de l'entité avec LINQ à l'aide du nom de champ Dyanmic

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

Question

J'ai créé un écran de recherche dynamique dans ASP.NET MVC. J'ai récupéré les noms de champs de l'entité par réflexion afin de permettre à l'utilisateur de choisir les champs sur lesquels il souhaitait effectuer une recherche au lieu d'afficher tous les champs de la vue.

Lorsque le résultat de la recherche est renvoyé au contrôleur, je reçois un FormCollection contenant le nom du champ et la valeur. Je ne sais pas combien de champs sont recherchés et le FormCollection ne contient que des champs choisis par l'utilisateur.

Je veux pouvoir prendre ce nom de champ et l'appliquer à mon instruction LINQ lorsque j'interroge la base de données, par exemple:

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

Où j'ai "utiliser la chaîne de clé comme nom de champ", ce serait comme p => p.NomPremier == fieldValueDictionary [clé] où clé = "Prénom". J'ai essayé et je n'ai pas réussi à utiliser les arbres d'expression Lambda et j'ai eu un petit succès avec Dynamic LINQ. La seule autre alternative est de faire quelque chose comme:

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

UPDATE : J'ai effectué des recherches sur les arbres d'expression Lambda à travers les publications suivantes:

créer dynamiquement des expressions lambdas + linq + OrderByDescending

Problème de paramètre avec Expression.Lambda ()

LINQ: passage de l'expression lambda en tant que paramètre à exécuter et à retourner par méthode

J'ai eu jusqu'à obtenir un lambda pour produire ce qui suit: "p => p.FirstName", mais je ne peux pas que cela fonctionne dans un emplacement. Aucune suggestion? Mon code est ci-dessous:

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

Réponse acceptée

Après beaucoup plus d'essais et d'erreurs et de recherches, j'ai accidentellement trouvé un autre poste SO qui couvre le même sujet:

InvalidOperationException: Aucune méthode 'Où' sur le type 'System.Linq.Queryable' n'est compatible avec les arguments fournis

Voici mon code modifié qui fonctionne:

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

Avec quelques modifications, espérons-le, assez faciles, je devrais pouvoir le faire fonctionner avec n'importe quel type.

Merci encore pour vos réponses Ani & John Bowen


Réponse populaire

Avez-vous essayé d'obtenir la valeur de PropertyInfo?

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



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi