2009-07-17 6 views
1

(Le titre de cette question n'est pas le meilleur, mais je ne suis pas sûr comment d'autre mot, il!)Construire une requête LINQ basée sur bools

Je travaille sur un formulaire de recherche qui contient une liste de contrôle des valeurs. Fondamentalement, un élément coché signifie «inclure ce type dans la recherche». Quelque chose comme ceci:

Search for item: __________ 
Search in: 
     [ ] Fresh Foods 
     [ ] Frozen Foods 
     [ ] Beverages 
     [ ] Deli Counter 

J'ai un objet pour représenter cette recherche:

class FoodSearchCriteria{ 
    public string SearchString {get;set;} 
    public bool SearchFreshFoods {get;set;} 
    public bool SearchFrozenFoods {get;set;} 
    public bool SearchBeverages {get;set;} 
    public bool SearchDeliCounter {get;set;} 
} 

La seule façon que je peux penser à faire cette atmosphère est comme ceci:

public IList<FoodItem> FindFoodItems(FoodSearchCriteria criteria) 
// in reality, this is a fuzzy search not an exact match 
var matches = _DB.FoodItems.Where(x => x.FoodTitle == SearchString); 

var inCategories = new List<FoodItem>(); 

if (criteria.SearchFreshFoods) 
    inCategories.Add(matches.Where(x => x.Type == 'Fresh Foods')); 
if (criteria.SearchFrozenFoods) 
    inCategories.Add(matches.Where(x => x.Type == 'Frozen Foods')); 
//etc etc 

return inCategories; 
} 

Cela se sent comme une odeur de code pour moi, quelle serait une meilleure façon de l'aborder?

Répondre

3

Avez-vous essayé:

List<string> types = new List<string>(); 

if (criteria.SearchFreshFoods) { types.Add("Fresh Foods"); } 
if (criteria.SearchFrozenFoods) { types.Add("Frozen Foods"); } 
if (criteria.SearchBeverages) { types.Add("Beverages"); } 
if (criteria.SearchDeliCounter) { types.Add("Deli Counter"); } 

return _DB.FoodItems.Where(x => x.FoodTitle == SearchString && 
           types.Contains(x.Type)); 

Cela signifie une seule requête SQL, ce qui est à portée de main.

Vous pouvez certainement factoriser le type FoodSearchCriteria pour le rendre plus facile à construire la liste si ...

+0

N'hésitez pas à élaborer sur ce refactoring que vous avez en tête :) – Kirschstein

+0

Pas sûr de la main ... mais à tout le moins, il serait logique de mettre le code pour construire la liste * dans * cette classe. –

5

Jetez un oeil à PredicateBuilder

PredicateBuilder predicate = PredicateBuilder.False<FoodItem>(); 
if (criteria.SearchFreshFoods) 
{ 
    predicate = predicate.Or(x => x.Type == 'Fresh Foods'); 
} 
if (criteria.SearchFrozenFoods) 
{ 
    predicate = predicate.Or(x => x.Type == 'Frozen Foods')); 
} 
... 

_DB.FoodItems.Where(predicate); 
+0

Looks incompleet. pb == prédicat? – Dykam

+0

Oui. Toutes mes excuses, maintenant fixées. –

0

J'ai pas le temps d'examiner, mais cela pourrait être une solution non testé.

class SearchItem 
{ 
    string Name {get; set;} 
    bool IsSelected {get; set;} 
} 

class FoodSearchCriteria 
{ 
    String searchText {get; set;} 
    IList<SearchItem> SearchItems{ get; } 
} 

public IList<FoodItem> FindFoodItems(FoodSearchCriteria criteria) 
// in reality, this is a fuzzy search not an exact match 
var matches = _DB.FoodItems.Where(x => x.FoodTitle == criteria.SearchText && 
             criteria.SearchItems.Where(si => si.IsSelected).Contains(i => i.Name == x.Type)); 

return mathces; 
} 
Questions connexes