2010-05-05 3 views
4

J'ai une requête LINQ to SQL retournant des lignes d'une table dans un objet IQueryable. Je veux ensuite effectuer une requête SQL "WHERE ... IN ...." sur les résultats. Cela fonctionne très bien en utilisant ce qui suit. (Retour des résultats avec id ID1 ID2 ou ID3)Dynamic "WHERE IN" sur IQueryable (linq to SQL)

sQuery = "ID1,ID2,ID3"; 
string[] aSearch = sQuery.Split(','); 
items = items.Where(i => aSearch.Contains(i.ID)); 

Ce que je voudrais être en mesure de le faire, est la même opération, mais pas à préciser la partie i.ID. Donc, si j'ai la chaîne du nom de champ que je veux appliquer la clause "WHERE IN", comment puis-je l'utiliser dans la méthode .Contains()?

Répondre

3

Il y a plusieurs façons de le faire. Une façon consiste à utiliser Dynamic Linq. Une autre façon est d'utiliser Predicate Builder.

+0

Robert, merci pour votre message. Dynamic Linq a l'air de me permettre de spécifier le champ comme une requête basée sur une chaîne, ce que je veux, mais je ne suis pas sûr qu'il supporte la clause SQL IN. Predicate Builder ressemble à ce que je pourrais créer une expression en chaînant les expressions Predicate.Or ensemble, mais je ne sais pas comment je peux utiliser ma chaîne de nom de colonne dans chacun d'eux. J'ai essayé par la réflexion, et en appelant la méthode Equals, mais pas encore de chance. – matt

1

Vous devez construire un arbre d'expression. Il finira par ressembler à ceci (code partiel, ne compilera pas). Celui-ci contient à la fois et est égal. Utilisé dans ce projet: http://weblogs.asp.net/rajbk/archive/2010/04/15/asp-net-mvc-paging-sorting-filtering-a-list-using-modelmetadata.aspx

var param = Expression.Parameter(filterType, propertyName); 
var left = Expression.Property(param, filterType.GetProperty(propertyName)); 
var right = Expression.Constant(propertyValue, modelMetaData.ModelType); 

LambdaExpression predicate = null; 

if (searchFilterAttribute.FilterType == FilterType.Contains) 
{ 
    var methodContains = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 
    var filterContains = Expression.Call(left, methodContains, right); 
    predicate = Expression.Lambda(filterContains, param); 
} 
else 
{ 
    var expr = Expression.Equal(left, right); 
    predicate = Expression.Lambda(expr, param); 

} 

var expression = Expression.Call(
    typeof(Queryable), 
    "Where", 
    new Type[] { queryable.ElementType }, 
    queryable.Expression, 
    predicate); 

queryable = queryable.Provider.CreateQuery<T>(expression); 

je réécrire cela en une méthode d'extension réutilisable (il est trop spécifique à ce projet pour le moment) et blog à ce sujet.

+0

Merci pour votre réponse Raj, mais je pense que cela me permettra de vérifier si un champ contient une chaîne. Je veux effectuer un équivalent SQL IN en utilisant contient. c'est-à-dire que array contient un champ, plutôt qu'un champ contient une chaîne. – matt