2012-03-07 44 views
1

這是我的代碼:你知道另一種方式來做這個「大規模」linq過濾嗎?

// I STORE THE USER SELECTED VALUES 
IList<string> SelectedCity = (from CheckBox loc in panelCity.Controls.OfType<CheckBox>() 
           where loc.Checked 
           select loc.InputAttributes["value"]).ToList(); 

IList<string> SelectedCategories = (from CheckBox strut in panelCategories.Controls.OfType<CheckBox>() 
            where strut.Checked 
            select strut.InputAttributes["value"]).ToList(); 

// I GET ALL RECORDS 
IList<Hotel> Hotels = (from Hotel hotel in new Hotels() 
         orderby hotel.Titolo ascending 
         select hotel).ToList(); 

// I FILTER THEM 
if (SelectedCity.Count > 0) 
    Hotels = Hotels.Where(o => o.City != null && SelectedCity.Contains(o.City.UniqueID)).ToList(); 

if (SelectedCategories.Count > 0) 
    Hotels = Hotels.Where(o => o.Category != null && SelectedCategories.Contains(o.Category.UniqueID)).ToList(); 

所以,你可以看到,我做了一些查詢,存儲從用戶選擇的值。對於每個酒店排,我騎自行車城市和類別的陣列。

這,有很多行,它非常昂貴。

你知道一些其他方法來優化研究嗎?

+0

您是否嘗試過使用'ToList()'只在最後結果如何?不要在這樣做的時候改變變量的類型。 – svick 2012-03-07 14:00:52

回答

1

最起碼,你可以combime你Where子句入上面的LINQ聲明:

 
IList Hotels = (from Hotel hotel in new Hotels() 
       where SelectedCity.Count > 0 && hotel.City != null && SelectedCity.Contains(hotel.City.UniqueID) 
       where SelectedCategories.Count > 0 && hotel.Category != null && SelectedCategories.Contains(hotel.Category.UniqueID) 
       orderby hotel.Titolo ascending 
       select hotel).ToList();
4

把你的城市和類別爲HashSet<string>,以節省查詢時間:

HashSet<string> selectedCities = new HashSet<string>(SelectedCity); 
HashSet<string> selectedCategories = new HashSet<string>(SelectedCategories); 

您也不需要使用ToList(),直到您的查詢完全組裝好,否則您將遍歷多次:

var hotels = from Hotel hotel in new Hotels() 
      select hotel; 

if (SelectedCity.Any()) 
    hotels = hotels.Where(o => o.City != null && selectedCities.Contains(o.City.UniqueID)); 

if (SelectedCategories.Any()) 
    hotels = hotels.Where(o => o.Category != null && selectedCategories.Contains(o.Category.UniqueID)); 

最後,排序可以做到的,一旦你已經過濾掉所有你不想這樣你就少排序項酒店

hotels = hotels.OrderBy(h=> h.Titolo); 

而且作爲最後一步兌現的結果:

Hotels = hotels.ToList(); 
+0

那麼你是說存儲一個列表到哈希集? – markzzz 2012-03-07 14:06:39

+0

是的 - 由於您正在尋找城市和類別,因此不應該有任何重複,因此您可以使用哈希集O(1)查找時間。 – BrokenGlass 2012-03-07 14:09:20

+0

@markzzz:澄清一下:酒店是來自數據庫還是這是一個內存集合? – BrokenGlass 2012-03-07 14:16:12

0

只能從這裏猜測,但重大打擊似乎是得到所有的酒店,看到你只需要城市,或查詢後續類別。

如果您只是選擇需要的輸入以獲得匹配的ID,那麼選擇符合條件的酒店可能會有所改進。

0

將所有酒店加載到內存中執行搜索是非常無效的;但是,如果您未加載所有酒店,則無法在集合上撥打Contains()。相反,您可以使用PredicateBuilderJoseph Albahari site構建謂詞,該謂詞可用於僅獲取符合條件的酒店。

var inSelectedCities = PredicateBuilder.True<Hotel>(); 
foreach(var city in SelectedCity) 
{ 
    string temp = city; 
    inSelectedCities = inSelectedCities.Or(h => h.City.UniqueId == temp); 
} 
var inSelectedCategories = PredicateBuilder.True<Hotel>(); 
foreach(var category in SelectedCategories) 
{ 
    string temp = category; 
    inSelectedCategories = inSelectedCategories.Or(h => h.Category.UniqueId == temp) 
} 
var hotels = Hotels 
       .Where(inSelectedCities.Or(inSelectedCategories)) 
       .ToList(); 
0

在訪問數據庫的酒店構造函數中,性能問題顯而易見。如果該構造函數使用LinqToSql或LinqToEntities,則應該將Expression<Func<Hotel, bool>>傳遞給那裏,以調用Queryable.Where並在數據庫端完成一些過濾。

如果構造函數不使用Linq,你將有可能通過將標準列出了溝通的過濾另一種方式......。

相關問題