C# 查询实体框架的通用方法
我想通过C# 查询实体框架的通用方法,c#,entity-framework,generics,C#,Entity Framework,Generics,我想通过IEnumerable获得过滤实体框架IQueryable的通用方法。其签名可能如下所示: public static IQueryable<TItem> ApplyFilter<TItem, TEnum>(IQueryable<TItem> items, IEnumerable<TEnum> enumValues, Expression<Func<TItem, IEnumerable<TEnum>, bool>
IEnumerable
获得过滤实体框架IQueryable
的通用方法。其签名可能如下所示:
public static IQueryable<TItem> ApplyFilter<TItem, TEnum>(IQueryable<TItem> items, IEnumerable<TEnum> enumValues, Expression<Func<TItem, IEnumerable<TEnum>, bool>> predicate)
{
return items.Where(??????);
}
IQueryable<Request> requests = service.GetAllRequests();
IEnumerable<RequestState> states = new RequestState[] {RequestState.Active, RequestState.Closed};
Expression<Func<Request, IEnumerable<RequestState>, bool>> predicate = (r, s) => s.Contains(r.State);
requests = ApplyFilter(requests, states, predicate);
公共静态IQueryable ApplyFilter(IQueryable项、IEnumerable枚举值、表达式谓词)
{
退货项目。其中(???);
}
我想可以这样称呼它:
public static IQueryable<TItem> ApplyFilter<TItem, TEnum>(IQueryable<TItem> items, IEnumerable<TEnum> enumValues, Expression<Func<TItem, IEnumerable<TEnum>, bool>> predicate)
{
return items.Where(??????);
}
IQueryable<Request> requests = service.GetAllRequests();
IEnumerable<RequestState> states = new RequestState[] {RequestState.Active, RequestState.Closed};
Expression<Func<Request, IEnumerable<RequestState>, bool>> predicate = (r, s) => s.Contains(r.State);
requests = ApplyFilter(requests, states, predicate);
IQueryable requests=service.GetAllRequests();
IEnumerable states=new RequestState[]{RequestState.Active,RequestState.Closed};
表达式谓词=(r,s)=>s.Contains(r.State);
请求=ApplyFilter(请求、状态、谓词);
但在方法的体内应该是什么呢?如何将
Expression
转换为Expression
,用作“Where”方法的参数?它能与实体框架一起工作吗?IMO,谓词应该在您的ApplyFilter
方法中(关注点方面)。
一种可能的编码方法是:
public static IQueryable<TItem> ApplyFilter<TItem, TEnum>(IQueryable<TItem> items,
IEnumerable<TEnum> enumValues, Expression<Func<TItem,TEnum>> enumField)
{
return items.Where(i => enumValues.Contains(enumField(i)));
}
当我实现夏普的答案时,我发现其实完全可以做我想要做的事情。关键是要使用从ExpressionVisitor继承的自定义类。此类将用表达式树中出现的
IEnumerable
参数的实际值替换该参数。我的最终代码:
public static IQueryable<TFilteredItem> ApplyFilter<TFilteredItem, TEnum>(IQueryable<TFilteredItem> items, IEnumerable<TEnum> enumValues, Expression<Func<TFilteredItem, IEnumerable<TEnum>, bool>> predicate)
{
ParameterExpression itemParam = predicate.Parameters[0];
ParameterExpression enumsParam = predicate.Parameters[1];
var em = new ExpressionModifier<IEnumerable<TEnum>>(enumsParam.Name, enumValues);
Expression predicateBody = em.Modify(predicate.Body);
return items.Where(Expression.Lambda<Func<TFilteredItem, bool>>(predicateBody, new[] { itemParam }));
}
public class ExpressionModifier<T> : ExpressionVisitor
{
private readonly string parameterName;
private readonly T newValue;
public Expression Modify(Expression expression)
{
return Visit(expression);
}
public ExpressionModifier(string parameterName, T newValue)
{
this.parameterName = parameterName;
this.newValue = newValue;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return node.Name == this.parameterName ? Expression.Constant(this.newValue, node.Type) : base.VisitParameter(node);
}
}
是的,这可能是我将使用的解决方案。我只是希望得到更一般的东西,即不局限于“Contains”方法。谢谢你的回答。