4

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

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

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

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

怎么做?

4

2 回答 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();
于 2014-01-29T19:29:14.330 回答
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只是一个包含不同员工属性的简单类。

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

于 2014-01-29T16:37:53.720 回答