C# Linq EF查询的一种通用过滤方法

C# Linq EF查询的一种通用过滤方法,c#,linq,entity-framework,generic-method,C#,Linq,Entity Framework,Generic Method,我有各种类型的EF实体,它们都有一个名为“Employee”的导航属性。生成报告时,用户可以选择根据不同的员工属性(成本中心、性别等)筛选报告 目前,我正在逐个筛选每个查询,例如: var courses = context.Courses .Where(c => c.Employee.CostCenterID == ccID && c.Employee.Rank == rankID

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

目前,我正在逐个筛选每个查询,例如:

var courses = context.Courses
              .Where(c => c.Employee.CostCenterID == ccID
                     && c.Employee.Rank == rankID
                     ....
                    )
                    .ToList();
public partial class Course: IFilterable
{
}
真正的过滤器代码要长得多,但这只是一个提示。无论如何,有没有办法创建一个通用方法来过滤员工的结果?我将提供给此筛选方法的所有实体都将具有
Employee
导航属性。我只需提供一个
IQueryable
ObjectSet
,然后获得一个过滤后的
IQueryable
ObjectSet


怎么做?

我刚想出来!由于我们无法在泛型方法中添加约束来检查某个属性,因此我使用了一个接口:

public interface IFilterable
{
    Employee Employee
    {
        get;
        set;
    }
}
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 );
}
然后,我添加了分部类以继承具有
Employee
导航属性的不同实体的上一个接口,例如:

var courses = context.Courses
              .Where(c => c.Employee.CostCenterID == ccID
                     && c.Employee.Rank == rankID
                     ....
                    )
                    .ToList();
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;
}
注意:
SearchCriteria
只是一个简单的类,它包含不同的员工属性


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

如果要避免实现接口:

public interface IFilterable
{
    Employee Employee
    {
        get;
        set;
    }
}
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 );
}
公共表达式EmployeeFilterDelegateExp(
int costCenterId,
内特兰基德酒店
{
var parm=表达式参数(typeof(tenty),“entity”);
var employeeProperty=Expression.Property(parm,“Employee”);
return(Expression)Expression.Lambda(
安达尔索(
Expression.Equal(Expression.Property(employeeProperty,“CostCenterID”),
表达式.常量(costCenterId)),
Expression.Equal(Expression.Property(雇员财产,“等级”),
表达式.常数(rankId)),
帕尔姆);
}
用法:

var courses = context.Courses
    .Where( EmployeeFilterDelegateExp<Course>( ccID, rankID ) )
    .ToList();
var courses=context.courses
.Where(员工过滤器delegateexp(ccID,兰基德))
.ToList();

我认为您应该将此代码作为问题发布,而不是回答自己的问题并要求更好solutions@SergeyBerezovskiy当我问这个问题的时候,我不知道答案,我在发帖后就知道了。所以我不想做辅导之类的。你知道答案突然出现在你脑海中的那些时刻…@SergeyBerezovskiy,谢谢。我还发表了代码评论。如果属性实现映射到不同的属性,接口属性(Employee)是否适用于LINQ to SQL或实体框架LINQ类?