我想知道以列表作为条件来编写最有效的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();
但是我收到以下错误:
Unable to create a constant value of
type ‘Closure type’. Only primitive
types (‘such as Int32,String,and
Guid’) are supported in this context.
解决方法
不要使用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();
}
}