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

4
我有各种类型的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个回答

3

如果你想避免实现一个接口:

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

我刚刚想到了一个办法!由于我们无法在泛型方法中添加约束以检查某个属性,所以我使用接口来实现:

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只是一个简单的类,用于保存不同的员工属性。
如果有更好的方法,请发布它。

我认为你应该将这段代码发布在http://codereview.stackexchange.com/上作为问题,而不是回答自己的问题并寻求更好的解决方案。 - Sergey Berezovskiy
1
@SergeyBerezovskiy 在提问时,我并不知道答案,但在发布问题后我想到了答案。所以我并没有像做教程一样。你知道那种答案突然出现在脑海中的时刻... - Nean Der Thal
1
@SergeyBerezovskiy 无论如何,谢谢。我也在代码审查中发布了。 - Nean Der Thal
如果接口属性(Employee)的实现映射到不同的属性,那么它是否适用于LINQ-to-SQL或Entity Framework LINQ类? - Petrus Theron

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