I have various types of EF entities, all of them have a navigation property called "Employee". When generating reports the user will have the option to filter the report according to the different employee propertoes (Cost Center, gender, etc.).
Currently I am filtering each query individually, for example:
var courses = context.Courses
.Where(c => c.Employee.CostCenterID == ccID
&& c.Employee.Rank == rankID
....
)
.ToList();
The real filter code is much more longer but this was just a hint. Anyway, is there a way to create a generic method to filter the result by the employee? all the entities I will supply to this filter method will have an Employee
navigation property. I will simply supply a IQueryable<entity>
or ObjectSet<entity>
and then get a filtered IQueryable<entity>
or ObjectSet<entity>
.
How to do that?
If you want to avoid implementing an interface:
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 );
}
Usage:
var courses = context.Courses
.Where( EmployeeFilterDelegateExp<Course>( ccID, rankID ) )
.ToList();
I just figured it out! since we can not add a constraint in generic methods to check for a certain property, I managed to do it using an interface:
public interface IFilterable
{
Employee Employee
{
get;
set;
}
}
Then, I added partial classes to inherit the previous interface for different entities that has the Employee
navigation property, for example:
public partial class Course: IFilterable
{
}
Then created the following generic method:
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;
}
then simply I can use it like this on any class that inherits IFilterable
:
var list = context.Courses.Filter(sc).ToList();
Note: the SearchCriteria
is just a simple class that holds different employee properties.
Please if there is a better way of doing this, post it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.