带有实体框架的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执行此查询?
您可以使用Id集合的Contains
(int
)并将其应用于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
类,它提供了一些扩展方法,如Or
、And
、Not
,因此,您可以尝试以下方法:
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();