动态where子句的最简单方法

3

在使用EF生成动态where子句时,我感到信息过载。一些解决方案似乎非常陈旧(我正在使用.NET 4.5和EF 5)。

这是我的代码:

public enum PersonTypes
{
    Lazy = 1,
    Awesome = 2,
    SuperHero = 3
}

public bool IncludeLazyPeople { get; set; }
public bool IncludeAwesomePeople { get; set; }
public bool IncludeSuperHeroPeople { get; set; }

使用EF,我需要查询与提供的布尔值匹配的人员类型。

我研究了这个链接: http://www.albahari.com/nutshell/predicatebuilder.aspx

以下是我得出的结果:

// create an expression that would include none of the person types
var personTypeExpression = PredicateBuilder.False<DAL.Models.Person>();

if (IncludeLazyPeople)
    personTypeExpression = personTypeExpression.Or(person => person.PersonType == (int)PersonTypes.Lazy);

if (IncludeAwesomePeople)
    personTypeExpression = personTypeExpression.Or(person => person.PersonType == (int)PersonTypes.Awesome);

if (IncludeSuperHeroPeople)
    personTypeExpression = personTypeExpression.Or(person => person.PersonType == (int)PersonTypes.SuperHero);

// filter the people for all included types
var filteredPeople = ctx.People.Where(personTypeExpression);

由于我没有包含 AsExpandable 扩展,所以那个方法失败了。在尝试之前,我想知道是否有更简单的方法?
2个回答

0
var query = context.People.AsQueryable();

if (IncludeLazyPeople)
    query = query.Where(person => person.PersonType == (int)PersonTypes.Lazy);

if (IncludeAwesomePeople)
    query = query.Where(person => person.PersonType == (int)PersonTypes.Awesome);

if (IncludeSuperHeroPeople)
    query = query.Where(person => person.PersonType == (int)PersonTypes.SuperHero);

如果你只需要 AND 逻辑,那么你可以在查询中调用额外的 Where() 方法。否则,如果你需要更强大的选项,那么就使用谓词构建器或 System.Linq.Expressions


糟糕,我的例子应该使用OR而不是AND。我已经更新了问题。我正在研究System.Linq.Expressions。 - mbursill

0
ParameterExpression p = Expression.Parameter(typeof(Person));
Expression personType = Expression.MakeMemberAccess(p, typeof(Person).GetProperty("PersonType"));
Expression personTypeExpression = Expression.Constant(false);
if (IncludeLazyPeople)
    personTypeExpression = Expression.OrElse(personTypeExpression, Expression.Equal(personType, Expression.Constant((int)PersonTypes.Lazy)));

//... same as above only with different Constant values

// filter the people for all included types
var filteredPeople = ctx.People.Where(Expression.Lambda<Func<Person,bool>>(personTypeExpression,p));

这应该大致符合您的要求。没有在编译器中检查,希望没有太多的拼写错误。


只是 OrElse 上缺少了一个闭合括号,否则它运行得很好。 :-) - mbursill
@mbursill:另外,我刚刚注意到,您的目标是EF5,.net 4.5。您知道您可以在模型上使用枚举而不是整数吗?在这种情况下,此代码保持完全相同,只需删除“(int)”即可... - TDaver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接