我有各种类型的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>
。
怎么做?
答案 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
只是一个包含不同员工属性的简单类。
如果有更好的方法,请发布。