2014-01-29 27 views
4

我有各种类型的EF实体,它们都有一个名为“Employee”的导航属性。生成报告时,用户可以根据不同的员工特征(成本中心,性别等)筛选报告。Linq-EF查询的通用过滤方法

目前我单独滤波过程中每个查询,例如:

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

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

如何做到这一点?

回答

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只是一个简单的类,用于保存不同的员工属性。

请如果有更好的方法做到这一点,张贴它。

+0

我想你应该张贴此代码问题上http://codereview.stackexchange.com/代替回答你自己的问题,并要求更好的解决方案 –

+0

@SergeyBerezovskiy在问这个问题时,我不知道答案,在发布问题后我想出了答案。所以我不喜欢给教程什么的。你知道那些答案刚刚出现在你脑海中的时刻... –

+1

@SergeyBerezovskiy无论如何,谢谢。我也在代码评论中发布。 –

1

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

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();