簡體   English   中英

如何在“WHERE”條件下使用List編寫LINQ to Entities查詢

[英]How to write a LINQ to Entities query with List in a “WHERE” condition

我想知道以列表作為條件編寫最有效的LINQ( 編輯 :實體)查詢。 這就是事情。

可以說我們有以下數據結構:

 public class Recipe
 {
   public int Id;
   public string Name;
   public List<Ingredient> IngredientList;
 }

 public class Ingredient
 {
   public int Id;
   public string Name;
 }

現在,我想做一個查詢,搜索所有具有所有給定成分的食譜。

 public List<Recipe> GetRecipesWhichHaveGivenIngredients(List<Ingredients> ingredients)
 {
   List<Recipe> recipes;

   using (DataContext context = new DataContext())
   {
    //efficient LINQ query goes here
    recipes = context.Recipes.Where(recipe => /*medaCode recipe.IngredientList.Contains(ingredients) */).ToList();
   }
   return recipes;
 }

基本上這是如何確定給定集合是否是另一集合的子集的問題。

我嘗試過以下查詢(主要思想是使用Intersect操作):

List<Recipe> recipes = dataContext.Recipes.Include("Ingrediens").Where(rec => rec.IngredientList.Select(ingr => ingr.Id).Intersect(ingredients.Select(sy =>  sy.Id)).Count() == ingredients.Count).ToList();

但是我收到以下錯誤:

無法創建“閉包類型”類型的常量值。 在此上下文中僅支持原始類型(例如Int32,String和Guid')。

好吧,如果IngredientList真的是List<T> ,你將能夠做到:

recipes = context.Recipes.Where(recipe => recipe.IngredientList.Exists(i => i.Id == ingredient.Id)).ToList();

但這意味着需要填充所有列表。 由於這看起來像LINQ to SQL查詢,我猜測IngredientList只是一個連接表......? 在這種情況下,您將沒有完整列表,但您仍然可以執行類似的操作:

recipes = context.Recipes.Where(recipe => recipe.IngredientList.Count(i => i.Id == ingredient.Id) > 0).ToList();

...它應該仍然只查詢一次sql server。

編輯

正如評論中剛才指出的那樣,這並沒有完全回答這個問題。 至於包含所有搜索,我認為沒有循環輸入就可以完成。 好的一點是,這可以在不枚舉IEnumerable recipes情況下完成,因此下面的代碼仍然只需用一個查詢就可以訪問sql server一次:

var recipes = context.Recipes.AsEnumerable<Recipe>();

ingredients.ForEach(i =>
    var recipes = recipes.Where(r =>
        r.IngredientList.Count(ii => ii.Id == i.Id) > 0
    );
);

return recipes.ToList();

在命中ToList()之前,不會執行查詢。

不要使用List<Ingredient>作為您想要找到的成分; 使用HashSet<Ingredient>IsProperSubsetOf方法,該方法接受一個集合作為其參數:

.Where(x => ingredients.IsProperSubsetOf(x.IngredientList))

除了作為O(n + m)操作之外,還有一個額外的好處,就是可以在看到它時告訴你它正在做什么。

編輯

如果上述情況不明確:

public List<Recipe> GetRecipesWhichHaveGivenIngredients(HashSet<Ingredient> ingredients)
{
   using (DataContext context = new DataContext())
   {
       return context.Recipes
           .Where(x => ingredients.IsProperSubsetOf(x.IngredientList)  
           .ToList();
   }
 }

不知道這是否適用於Linq2SQL,但在Linq2Object中,這有效:

public static class Util
{
    public static List<Recipe> GetRecipesWhichHaveGivenIngredients(this List<Recipe> recipies, List<Ingredient> ingredients)
    {
        int icount=ingredients.Count;

        var res = recipies.Where(r => r.IngredientList.Where(i => ingredients.Contains(i)).Count() == icount).ToList();
        return res;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM