带有实体框架的Linq中的动态Where

本文关键字:动态 Where Linq 实体 框架 | 更新日期: 2023-09-27 18:21:48

我编写了函数

    private Func<CategorizedPosts, bool> CompileExpression(IEnumerable<Category> categories)
    {
        Expression predicateBody;
        ParameterExpression pe = Expression.Parameter(typeof(CategorizedPosts), "post");
        Expression left = Expression.Property(pe, typeof(CategorizedPosts).GetProperty("CATEGORY_ID"));
        Expression right = Expression.Constant(categories.ElementAt(0).ID);
        Expression equal = Expression.Equal(left, right);
        predicateBody = equal;
        for (int i = 1, j = categories.Count() - 1; i < categories.Count(); ++i )
        {
            var category = categories.ElementAt(i);
            //y => y.CATEGORY_ID == 1 || y.CATEGORY_ID == 2)
            left = Expression.Property(pe, typeof(CategorizedPosts).GetProperty("CATEGORY_ID"));
            right = Expression.Constant(category.ID);
            equal = Expression.Equal(left, right);
            predicateBody = Expression.OrElse(predicateBody, equal);
        }
        var lll = Expression.Lambda<Func<CategorizedPosts, bool>>(predicateBody, pe);
        var compiled = lll.Compile();
        return compiled;
    }

它编译正常,但当我尝试运行这个查询时

            var ctx = db.Posts.Where(x => true);
            if(predicate != null)
            {
                ctx = ctx.Where(x => x.CategorizedPosts.Where(**predicate**).Count() > 0);
            }
            IList<Post> posts = ctx.OrderByDescending(x => x.CREATION_DATE).Skip((page - 1) * perPage).Take(perPage).Select(x => new Post 
            {
                POST_ID = x.ID,
                TYPE = new Type { ID = x.TYPE_ID, NAME = x.Types.NAME },
                AUTHOR = new Author()
                {
                    ID = x.AUTHOR_ID,
                    NAME = x.Authors.NAME,
                },
                CATEGORIES = x.CategorizedPosts.Select(y => new Category() { ID = y.CATEGORY_ID, NAME = y.Categories.NAME }),
                CREATION_DATE = x.CREATION_DATE,
            }).ToList();

EF引发关于实体数据提供程序的内部错误1025的异常。如何使用动态where执行此查询?

带有实体框架的Linq中的动态Where

您可以使用Id集合的Containsint)并将其应用于where,例如:

int[] categorieIds = categories.Select(x => x.Id).ToArray();
ctx = ctx.Where(x => x.CategorizedPosts.Any(c => categorieIds .Contains(c.Id));

一些提示

请记住,实体框架在Where方法中使用Expression<Func<T, bool>>,而不仅仅是Func<T, bool>

您也可以尝试应用PredicateBuilder类,它提供了一些扩展方法,如OrAndNot,因此,您可以尝试以下方法:

  var predicate = PredicateBuilder.False<Product>();
  foreach (string keyword in keywords)
  {
    string temp = keyword;
    predicate = predicate.Or (p => p.Description.Contains (temp));
  }
  return dataContext.Products.Where(predicate).ToList();