Linq-EF查询的通用过滤方法

时间:2014-01-29 16:09:24

标签: c# linq entity-framework generic-method

我有各种类型的EF实体,它们都有一个名为“Employee”的导航属性。生成报告时,用户可以根据不同的员工资产(成本中心,性别等)过滤报告。

目前我正在逐个过滤每个查询,例如:

var courses = context.Courses
              .Where(c => c.Employee.CostCenterID == ccID
                     && c.Employee.Rank == rankID
                     ....
                    )
                    .ToList();

真正的过滤器代码要长得多,但这只是一个提示。无论如何,有没有办法创建一个通用的方法来过滤员工的结果?我将提供给此过滤器方法的所有实体都将具有Employee导航属性。我只需提供IQueryable<entity>ObjectSet<entity>,然后过滤IQueryable<entity>ObjectSet<entity>

怎么做?

2 个答案:

答案 0 :(得分:2)

如果您想避免实现界面:

public Expression<Func<TEntity, bool>> EmployeeFilterDelegateExp<TEntity>( 
    int costCenterId, 
    int rankId )
{
    var parm = Expression.Parameter( typeof( TEntity ), "entity" );
    var employeeProperty = Expression.Property( parm, "Employee" );

    return ( Expression<Func<TEntity, bool>> )Expression.Lambda(
        Expression.AndAlso(
            Expression.Equal( Expression.Property( employeeProperty, "CostCenterID" ), 
                Expression.Constant( costCenterId ) ),
            Expression.Equal( Expression.Property( employeeProperty, "Rank" ), 
                Expression.Constant( rankId ) ) ),
        parm );
}

用法:

var courses = context.Courses
    .Where( EmployeeFilterDelegateExp<Course>( ccID, rankID ) )
    .ToList();

答案 1 :(得分:1)

我刚想通了!因为我们无法在泛型方法中添加约束来检查某个属性,所以我设法使用接口来完成:

public interface IFilterable
{
    Employee Employee
    {
        get;
        set;
    }
}

然后,我添加了部分类来继承具有Employee导航属性的不同实体的上一个接口,例如:

public partial class Course: IFilterable
{
}

然后创建了以下通用方法:

public static IQueryable<T> Filter<T>(this IQueryable<T> source, SearchCriteria sc) 
    where T : class, IFilterable
{
    var filtered = source.Where(e => e.Employee.CostCenterID == sc.CostCenterID 
        && e.Employee.Gender == sc.Gender);

     return filtered;
}

然后我就可以在任何继承IFilterable

的类上使用它
var list = context.Courses.Filter(sc).ToList();

注意:SearchCriteria只是一个包含不同员工属性的简单类。

如果有更好的方法,请发布。