2010-03-05 12 views
1

J'utilise LINQ to SQL et j'autorise les utilisateurs à configurer la requête en affectant des valeurs à queryStrings dans l'interface utilisateur. J'ai mis en place la requête primaire pour renvoyer un résultat IQueryable et continuer à affiner l'ensemble de résultats en continuant à agir sur l'objet IQueryable résultant. Tout fonctionne très bien et le code ressemble à ceLINQ to SQL - modification supplémentaire du jeu de résultats IQueryable avec Contient

var result = (from record in db.Companies 
select new Company 
{ 
    Id = record.Id, 
    Name = record.Name, 
    City = record.City, 
    Status = record.Status 
}); 
if (queryName != null && queryName!= "") 
{ 
    result = result.Where(p => p.Name.Contains(queryName)); 
} 

if (queryCity != null && queryCity!= "") 
{ 
    result = result.Where(p => p.City.StartsWith(queryCity)); 
} 

Maintenant, je veux étendre la requête de mon obtenir un ensemble correspondant d'éléments similaires à « IN CLAUSE » dans SQL. Où il y a une liste d'éléments à utiliser dans la requête, par ex.

string[] queryStatusList = {"x", "y" }; 

Et maintenant je peux écrire le code comme ceci et tout est encore OK.

var result = (from record in db.Companies 
where queryStatusList.Contains(record.status) 
    select new Company 
    { 
     Id = record.Id, 
     Name = record.Name, 
     City = record.City, 
     Status = record.Status 
    }); 
if (queryName != null && queryName!= "") 
{ 
    result = result.Where(p => p.Name.Contains(queryName)); 
} 

if (queryCity != null && queryCity!= "") 
{ 
    result = result.Where(p => p.City.StartsWith(queryCity)); 
} 

Mais, je ne veux pas avoir une clause where dans la requête initiale. Je veux construire à partir du résultat de requête affiné comme fait dans l'exemple précédent. Ma question est de savoir comment structurer une telle requête. J'ai essayé

if (queryStatusList != null && queryStatusList.Count() > 0) 
{ 
    result = result.Where(queryStatusList.Contains(result.Select(p => p.Status.ToString()))); 
} 

Mais je reçois une erreur de compilation: « Les arguments de type pour la méthode « System.Linq.Enumerable.Contains (System.Collections.Generic.IEnumerable, TSource) » ne peuvent pas être déduites de l'utilisation. Essayez de spécifier explicitement les arguments de type "J'ai essayé quelques variantes mais je ne suis pas sûr de savoir comment résoudre le problème.

Répondre

1

Je pense que si vous changez légèrement, il peut fonctionner:

if (queryStatusList != null && queryStatusList.Count() > 0) 
{ 
    result = result.Where(r=> queryStatusList.Contains(r.Status)); 
} 

D'autre part, vous voudrez peut-être envisager d'utiliser un PredicateBuilder pour construire un seul cas sélecteur de clause et de l'utiliser à la place. Le PredicateBuilder vous donnera plus de contrôle et la possibilité de créer des requêtes complexes avec un mélange de clauses AND et OR tout en les construisant dynamiquement.

var predicate = PredicateBuilder.True<Company>(); 

if (queryName != null && queryName!= "") 
{ 
    predicate = predicate.And(p => p.Name.Contains(queryName)); 
} 

if (queryCity != null && queryCity!= "") 
{ 
    predicate = predicate.And(p => p.City.StartsWith(queryCity)); 
} 

if (queryStatusList != null && queryStatusList.Count() > 0) 
{ 
    predicate = predicate.And(p => queryStatusList.Contains(p.Status)); 
} 

var result = db.Companies 
       .Select(c => new Company 
       { 
        Id = record.Id, 
        Name = record.Name, 
        City = record.City, 
        Status = record.Status 
       } 
       .Where(predicate); 
+0

Merci beaucoup. J'apprécie vraiment l'aide. J'ai passé plusieurs heures à essayer de le faire fonctionner. Une fois que vous voyez la réponse, il semble si facile. Merci encore ... – Rick

+0

Merci également pour l'excellent exemple de prédicat. Je n'ai jamais utilisé la classe PredicateBuilder. Ça a l'air très bien. – Rick