IQueryable Extension: créer expression lambda pour l'interrogation d'une colonne pour un mot clé
J'ai commencé avec le IQueryable les méthodes d'extension à partir de cet exemple sur CodePlex.
Ce que je crois que j'ai besoin est un IQueryable méthode d'extension pour "Où", où la signature de la méthode ressemble:
public static IQueryable<T> Where<T>(this IQueryable<T> source, string columnName, string keyword)
et de l'efficacité (en supposant T. columnName est de type string):
source.Where(p => p.ColumnName.Contains("keyword"))
à l'aide de la CodePlex exemple, je crois que je comprends comment il a obtenu le OrderBy méthode de travail, mais mon problème semble un peu plus complexe et je ne sais pas comment pour obtenir le Contient("mot clé") de la partie de travail.
Merci d'avance,
--Ed
Mise à jour: 9/13/2010 6:26pm PST
Je pensais que le suivant serait le travail, mais à la fin obtenir une NotSupportedException (L'expression LINQ nœud de type "Invoquer" n'est pas pris en charge dans LINQ to entities.) lorsque j'exécute l'expression via la fonction Count(). Des idées?
public static IQueryable<T> Where<T>(this IQueryable<T> source, string columnName, string keyword)
{
var type = typeof(T);
var property = type.GetProperty(columnName);
if (property.PropertyType == typeof(string))
{
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var sel = Expression.Lambda<Func<T, string>>(propertyAccess, parameter);
var compiledSel = sel.Compile();
return source.Where(item => compiledSel(item).Contains(keyword));
}
else
{
return source;
}
}
- - vous jamais résoudre le "non pris en charge dans LINQ to entities" problème?
Vous devez vous connecter pour publier un commentaire.
T
àstring
. Est-ce mieux?whereBody
est exactement ce quereturn source.Where(predicate);
dans mon code renvoie. Il commence par créer le prédicatp => p.ColumnName.Contains("keyword")
puis retournesource.Where(predicate)
.Bien une couple d'années plus tard, mais si quelqu'un a encore besoin de ce, elle est ici:
J'ai appelé ma méthode "A" juste pour le garder court, exemple d'utilisation:
Et vous pouvez concaténer pour le rendre encore plus expressive:
Par la manière, les "IsNull()" attaché à la de chaînes de caractères est juste une simple extension de la méthode:
La
.Contains("keyword")
partie est tout à fait exact dans votre exemple.C'est le
p.ColumnName
partie qui va causer des ennuis.Maintenant, il ya un certain nombre de façons de le faire, généralement de réflexion ou
Expression<>
, ni de ce qui est particulièrement efficace.Le problème ici, c'est en passant le nom de la colonne comme une chaîne de caractères, ce que vous faites pour annuler exactement la même chose LINQ a été inventé pour permettre.
Cependant, il ya probablement de meilleures façons d'accomplir votre tâche globale en plus de cette façon.
Donc, regardons d'autres moyens:
Vous voulez être en mesure de dire :
et la faire, c'est l'équivalent de
Comment 'bout nous allons avec:
ou
Ceux-ci sont facilement étendu pour les alternatives:
Voir, dans les génériques de type de l'objet fonctionne de manière dynamique. Ainsi, lorsque p.ColumnName est pris comme une chaîne de caractères, le contenu de la chaîne est exécuté.
Généralement pour une lambda expression que vous spécifiez, il analyse la chose dans une Expression et de produire la sortie au moment de l'exécution.
Si vous voyez mon post :
http://www.abhisheksur.com/2010/09/use-of-expression-trees-in-lamda-c.html
vous allez comprendre comment il fonctionne réellement.