Si vous êtes en mesure d'utiliser le IQueryable<T>
générique variante, cela devient un problème beaucoup plus facile puisque vous ne avez plus besoin CreateQuery
et vous pouvez exécuter directement contre la source IQueryable<T>
.
public static IQueryable<T> WhereLike<T>(this IQueryable<T> source, string propertyName,
string pattern)
{
if (source == null) throw new ArgumentNullException("source");
if (propertyName == null) throw new ArgumentNullException("propertyName");
var a = Expression.Parameter(typeof(T), "a");
var prop = Expression.PropertyOrField(a, propertyName);
var expr = Expression.Call(
typeof(SqlMethods), "Like",
null,
prop, Expression.Constant(pattern));
var lambda = Expression.Lambda<Func<T, bool>>(expr, a);
return source.Where(lambda);
}
Remarque deux points clés:
au lieu de propriétés que l'accaparement, si nous utilisons PropertyOrField nous pouvons soutenir correctement le code généré pour Linq-2-SQL qui peuvent exposerons les champs.
En outre, puisque nous exécutons contre la source IQueryable<T>
, nous devons créer une expression lambda à partir des résultats de notre "Like" MethodCallExpression
.
Si vous avez besoin de la variante non-générique, vous pouvez accomplir toujours la même chose, même si vous avez besoin d'envelopper votre Comme MethodCallExpression
dans un cas MethodCallExpression
afin qu'il soit bien structuré:
public static IQueryable WhereLike(this IQueryable source, string propertyName,
string pattern)
{
if (source == null) throw new ArgumentNullException("source");
if (propertyName == null) throw new ArgumentNullException("propertyName");
var a = Expression.Parameter(source.GetType().GetGenericArguments().First(), "a");
var prop = Expression.PropertyOrField(a, propertyName);
var expr = Expression.Call(
typeof(SqlMethods), "Like",
null,
prop, Expression.Constant(pattern));
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { source.ElementType },
source.Expression,
Expression.Lambda(expr, a));
return source.Provider.CreateQuery(whereCallExpression);
}
Vous pouvez appeler les deux variantes avec des jokers:
var data = source.WhereLike("ColumnName", "%o%");
ne pas le SQL comme opérateur ne fonctionne sur les chaînes? – Fran
@Fran Pourquoi est-ce important? – Servy
@Servy parce que s'il ne peut pas déterminer le type de la propriété, il pourrait essayer d'utiliser le WhereLike sur une propriété qui ne le supporte pas (DateTime, Double, ....) alors il obtiendrait une exception d'exécution quand ça arrive. Peut-être essaie-t-il de saisir le ElementType source et de rechercher le type de propriété en utilisant la réflexion. – Fran