【发布时间】:2014-08-16 22:04:51
【问题描述】:
我遇到的问题是,我想通过 Asp.net MVC 4 使用 EntityFramework 5 以一种很好的方式在应用程序中实现过滤。
过滤器是由这样的 json 字符串提供的:
filter
[ {"type":"string","value":"o","field":"name"},
{"type":"list","value":[1,2,5],"field":"type"},
{"type":"boolean","value":true,"field":"active"},
{"type":"numeric","comparison":"gt","value":0,"field":"order"},
{"type":"date","comparison":"lt","value":"11/28/2014","field":"updated_at"}
]
(其实就是ExtJs的网格过滤字符串)
我以这种方式实现了过滤器层次结构:FilterBase 类,然后是继承自 FilterBase 的 BooleanFilter、StringFilter 和 ComparisonFilterBase,然后是 DateFilter 和 NumericFilter
过滤器基础如下所示:
public abstract class FilterBase
{
public string Field { get; set; }
}
/// <summary>
/// Filter Base Class
/// </summary>
/// <typeparam name="T">The value type</typeparam>
/// <typeparam name="T2">The entity property's type</typeparam>
public abstract class FilterBase<T,T2>:FilterBase
{
public T Value { get; set; }
/// <summary>
/// Apply the filter
/// </summary>
/// <typeparam name="T1">The query main type, for instance, User if we are filtering users</typeparam>
/// <param name="query">The query over to make the filter</param>
/// <param name="field">A function that retrieves the main property's value</param>
/// <returns>The new Query</returns>
public abstract IQueryable<T1> Apply<T1>(IQueryable<T1> query, Func<T1, T2> field);
}
我的想法是在每个类中定义完成比较的方式。但为此,我需要知道要过滤的实体字段。这就是Apply 方法的field 参数的原因。例如:
foreach (var filterBase in filters)
{
switch (filterBase.Field.ToLower())
{
case "name":
query = ((StringFilter)filterBase).Apply(query, u => u.UserFirstName);
break;
case "lastname":
query = ((StringFilter) filterBase).Apply(query, u => u.UserLastName);
break;
case "login":
query = ((StringFilter)filterBase).Apply(query, u => u.UserLogin);
break;
case "role":
query = ((StringFilter)filterBase).Apply(query, u => u.UserRole.Name);
break;
case "email":
query = ((StringFilter)filterBase).Apply(query, u => u.UserEmail);
break;
case "active":
query = ((BooleanFilter)filterBase).Apply(query, u => u.Active);
break;
}
}
例如,这可能是NumericFilter 类:
public class NumericFilter : ComparisonFilterBase<float, float>
{
public override IQueryable<T1> Apply<T1>(IQueryable<T1> query, Func<T1, float> field)
{
switch (Comparison)
{
case Comparison.GreaterThan:
return query.Where(t => field(t) > Value);
case Comparison.LowerThan:
return query.Where(t => field(t) < Value);
case Comparison.Equals:
return query.Where(t => field(t) == Value);
}
return query;
}
}
这里的问题是 Linq to Entities 不适用于函数 field 的评估。我知道对于实例,此查询有效:query = query.Where(t => t.Age > Value);,唯一的问题是对于ExpressionTree,field 参数是一个函数,而不是对象访问部分。
我能做些什么来解决这个问题?
【问题讨论】:
标签: c# asp.net-mvc linq entity-framework linq-to-entities