我们有一个基于 OData conventions 的过滤器字符串
我们需要解析这个字符串,并在我们的 EntityFramework6 Model-First 生成的模型上执行 whereClause。
步骤:
- 使用 Breeze EdmBuilder nuget 包将我们的 DataModel
DbContext
转换为IEdmlModel
。 - 使用此
EdmModel
创建一个ODataQueryContext
。 - 使用
ODataQueryContext
和过滤器字符串创建一个FilterQueryOption
。
此时,我们有一个 FilterQueryOption
对象,里面有一个格式正确的表达式树。
我们的问题是当我们将这个表达式树转换为 Linq(在 EF Where 子句中使用)
我们在网上找到了这个方法来进行转换: (里面有异常信息)
static private Expression<Func<Countries, bool>> GetFilterExpression(FilterQueryOption filter)
{
var enumerable = Enumerable.Empty<Countries>().AsQueryable();
var param = Expression.Parameter(typeof(Countries));
if (filter != null)
{
enumerable = (IQueryable<Countries>)filter.ApplyTo(enumerable, new ODataQuerySettings());
// Exception : The query option is not bound to any CLR type. 'ApplyTo' is only supported with a query option bound to a CLR type.
var mce = enumerable.Expression as MethodCallExpression;
if (mce != null)
{
var quote = mce.Arguments[1] as UnaryExpression;
if (quote != null)
{
return quote.Operand as Expression<Func<Countries, bool>>;
}
}
}
return Expression.Lambda<Func<Countries, bool>>(Expression.Constant(true), param);
}
Sample code (Solution + sql script to generate simple DB)
有人可以帮忙吗?
最佳答案
赞Chad Carisch在评论中说,我需要使用typeof(Countries)
来构造ODataQueryContext
。
在那之后抛出的异常是“TestApiRest.Countries not found”。
所以我打开 edmx 文件属性并更改命名空间以匹配我的项目命名空间 (原来是TestApiRestModel,我改成了TestApiRest)
这是我的 ODataFilterConverter
类,它适用于我的第一个小测试:odataString = "Id eq 2"
public class ODataFilterConverter
{
private readonly IEdmModel m_model;
public ODataFilterConverter(TestRestApiEntities db)
{
m_model = db.GetEdm(); // *Breeze Labs: EdmBuilder*
}
public Expression<Func<T, bool>> Convert<T>(string odataString)
{
var filterQueryOption = GetFilterQueryOption(GetQueryContext<T>(), odataString);
return GetFilterExpression<T>(filterQueryOption);
}
private ODataQueryContext GetQueryContext<T>()
{
return new ODataQueryContext(m_model, typeof(T));
}
private FilterQueryOption GetFilterQueryOption(ODataQueryContext queryContext, string filter)
{
return new FilterQueryOption(filter, queryContext);
}
static private Expression<Func<T, bool>> GetFilterExpression<T>(FilterQueryOption filter)
{
var enumerable = Enumerable.Empty<T>().AsQueryable();
var param = Expression.Parameter(typeof(T));
if (filter != null)
{
enumerable = (IQueryable<T>)filter.ApplyTo(enumerable, new ODataQuerySettings());
var mce = enumerable.Expression as MethodCallExpression;
if (mce != null)
{
var quote = mce.Arguments[1] as UnaryExpression;
if (quote != null)
{
return quote.Operand as Expression<Func<T, bool>>;
}
}
}
return Expression.Lambda<Func<T, bool>>(Expression.Constant(true), param);
}
}
关于c# - 从 FilterQueryOption 获取 Linq 表达式抛出 CLR 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25668344/