C# 使用表达式树进行过滤

C# 使用表达式树进行过滤,c#,entity-framework,linq-to-entities,expression-trees,C#,Entity Framework,Linq To Entities,Expression Trees,我需要查询数据库并根据传递到函数中的参数进行过滤。我正在传递两个日期参数(用作日期范围)、一个名称和一个状态参数。所有参数都可以有“和”或“或”条件。基本上,我想构建一个基于参数填充的linq表达式,并将其传递给实体框架以返回结果集 如何使用最少的“如果”语句来实现这一点?如果您能用示例代码提供一个解释,那就太棒了。我正在努力学习表达式树,这样一个解释会有所帮助 在这一点上,我没有太多的代码。这就是我在这里发帖的原因。我可以列出方法签名。你到底在找什么 public enum EmployeeS

我需要查询数据库并根据传递到函数中的参数进行过滤。我正在传递两个日期参数(用作日期范围)、一个名称和一个状态参数。所有参数都可以有“和”或“或”条件。基本上,我想构建一个基于参数填充的linq表达式,并将其传递给实体框架以返回结果集

如何使用最少的“如果”语句来实现这一点?如果您能用示例代码提供一个解释,那就太棒了。我正在努力学习表达式树,这样一个解释会有所帮助

在这一点上,我没有太多的代码。这就是我在这里发帖的原因。我可以列出方法签名。你到底在找什么

public enum EmployeeStatus
{
    FullTime,
    PartTime,
    Contract
}

public IEnumerable<Employee> FilterEmployees(DateTime? startDate, 
    DateTime? endDate, string employeeName, EmployeeStatus employeeStatus)
{   }
public enum EmployeeStatus
{
全职,
兼职,
合同
}
公共IEnumerable筛选器员工(日期时间?开始日期,
DateTime?endDate,字符串employeeName,EmployeeStatus EmployeeStatus)
{   }
公共IQueryable筛选器员工(IQueryable查询、DateTime?startDate、DateTime?endDate、字符串employeeName、EmployeeStatus EmployeeStatus)
{
如果(起始日期!=null)
query=query.Where(x=>x.StartDate>=StartDate);
//等等。。。
返回查询;
}
公共IQueryable筛选器员工(IQueryable查询、DateTime?startDate、DateTime?endDate、字符串employeeName、EmployeeStatus EmployeeStatus)
{
如果(起始日期!=null)
query=query.Where(x=>x.StartDate>=StartDate);
//等等。。。
返回查询;
}
所有参数都可以有“和”或“或”条件。-可以考虑使用谓词生成器。看见为什么?因为这允许您编写单个查询,但仅在需要时添加AND/OR谓词。您可能需要也可能不需要此功能,但这是一个值得注意的好功能。在实际调用查询之前,不会有任何数据库开销—它提供了一种有条件地构建IQueryable的方法,您可能不希望在某些条件下与字段匹配。例如,前几天我用它来忽略输入字符串少于10个字符的搜索中最小长度为10的产品代码字段

这将允许您使用if条件添加和/或语句,例如:

public IQueryable<Employee> FilterEmployees(IQueryable<Employee> query, DateTime startDate, DateTime endDate, string employeeName, EmployeeStatus employeeStatus)
{
    var predicate = PredicateBuilder.True<Employee>();

    //All names starting with 'A'
    predicate = predicate.And(x => x.Name.StartsWith("A"));

    //Add a condition only if the employee is PartTime
    if (employeeStatus == EmployeeStatus.PartTime)
    {
        //Add condition for when they start
        predicate = predicate.And(x => x.StartDate >= startDate);
    }
    else
    {
        //Say we don't care about the start date for the other employee statuses,
        //but we want to add condition for when non-part-time employees are due to leave
        predicate = predicate.And(x => x.EndDate <= endDate);
        //or their name ends in 'z'
        predicate = predicate.Or(x => x.Name.EndsWith("z"));
    }

    IQueryable<Employee> employees = query.FindBy(predicate); //you should probably use a repository here to return your query

    return employees

}
public IQueryable FilterEmployees(IQueryable查询、DateTime startDate、DateTime endDate、字符串employeeName、EmployeeStatus EmployeeStatus)
{
var predicate=PredicateBuilder.True();
//所有以“A”开头的名称
predicate=predicate.And(x=>x.Name.StartsWith(“A”);
//仅当员工是兼职员工时才添加条件
if(employeeStatus==employeeStatus.PartTime)
{
//为它们何时开始添加条件
谓词=谓词和(x=>x.StartDate>=StartDate);
}
其他的
{
//假设我们不关心其他员工状态的开始日期,
//但我们想增加非兼职员工休假的条件
谓词=谓词和(x=>x.EndDate x.Name.EndsWith(“z”);
}
IQueryable employees=query.FindBy(谓词);//您可能应该在这里使用存储库来返回查询
返回员工
}
注意-这是用于演示的psuedo代码,可能有错误-请参阅上面的链接以了解正确的实现。

所有参数都可以有“和”或“或”条件。-可以考虑使用谓词生成器。看见为什么?因为这允许您编写单个查询,但仅在需要时添加AND/OR谓词。您可能需要也可能不需要此功能,但这是一个值得注意的好功能。在实际调用查询之前,不会有任何数据库开销—它提供了一种有条件地构建IQueryable的方法,您可能不希望在某些条件下与字段匹配。例如,前几天我用它来忽略输入字符串少于10个字符的搜索中最小长度为10的产品代码字段

这将允许您使用if条件添加和/或语句,例如:

public IQueryable<Employee> FilterEmployees(IQueryable<Employee> query, DateTime startDate, DateTime endDate, string employeeName, EmployeeStatus employeeStatus)
{
    var predicate = PredicateBuilder.True<Employee>();

    //All names starting with 'A'
    predicate = predicate.And(x => x.Name.StartsWith("A"));

    //Add a condition only if the employee is PartTime
    if (employeeStatus == EmployeeStatus.PartTime)
    {
        //Add condition for when they start
        predicate = predicate.And(x => x.StartDate >= startDate);
    }
    else
    {
        //Say we don't care about the start date for the other employee statuses,
        //but we want to add condition for when non-part-time employees are due to leave
        predicate = predicate.And(x => x.EndDate <= endDate);
        //or their name ends in 'z'
        predicate = predicate.Or(x => x.Name.EndsWith("z"));
    }

    IQueryable<Employee> employees = query.FindBy(predicate); //you should probably use a repository here to return your query

    return employees

}
public IQueryable FilterEmployees(IQueryable查询、DateTime startDate、DateTime endDate、字符串employeeName、EmployeeStatus EmployeeStatus)
{
var predicate=PredicateBuilder.True();
//所有以“A”开头的名称
predicate=predicate.And(x=>x.Name.StartsWith(“A”);
//仅当员工是兼职员工时才添加条件
if(employeeStatus==employeeStatus.PartTime)
{
//为它们何时开始添加条件
谓词=谓词和(x=>x.StartDate>=StartDate);
}
其他的
{
//假设我们不关心其他员工状态的开始日期,
//但我们想增加非兼职员工休假的条件
谓词=谓词和(x=>x.EndDate x.Name.EndsWith(“z”);
}
IQueryable employees=query.FindBy(谓词);//您可能应该在这里使用存储库来返回查询
返回员工
}

注意-这是用于演示的psuedo代码,可能有错误-请参阅上面的链接以了解正确的实现。

Cool,这很有效。那么,我们什么时候真正使用表达式树呢?酷,这很有效。那么,我们什么时候真正使用表达式树呢?很酷的回答。我不想在代码中有任何“if”语句,但我意识到这可能是不可能的。没有办法知道哪些变量填充了检查。没问题。我应该提到的另一件事是,你可以用fluent做一些类似“CASE-WHEN”的事情,比如:
query.OrderBy(x=>(x.ParentID.HasValue)?x.ParentID:x.ID)
。这基本上是lambda表达式中的三元if:see,我试图创建一个示例,说明您可以在何处使用它(orderby中的一个case):。我想让一个简单的父/子排序正常工作,但我似乎总是需要一个初步排序(例如,在
上键入
),但你明白了。我可能会提出我自己的问题