C# 从FilterQueryOption获取Linq表达式引发CLR异常
我们有一个基于 我们需要解析这个字符串,并在第一个生成的EntityFramework6模型上执行WHERE子句 步骤:C# 从FilterQueryOption获取Linq表达式引发CLR异常,c#,linq,odata,entity-framework-6,linq-expressions,C#,Linq,Odata,Entity Framework 6,Linq Expressions,我们有一个基于 我们需要解析这个字符串,并在第一个生成的EntityFramework6模型上执行WHERE子句 步骤: 使用Breeze EdmBuilder nuget软件包将数据模型DbContext转换为IEdmlModel 使用此EdmModel创建一个ODataQueryContext 使用ODataQueryContext和筛选器字符串创建一个FilterQueryOption 此时,我们有一个FilterQueryOption对象,其中包含一个格式良好的表达式树 我们的问题是当我
DbContext
转换为IEdmlModel
EdmModel
创建一个ODataQueryContext
ODataQueryContext
和筛选器字符串创建一个FilterQueryOption
FilterQueryOption
对象,其中包含一个格式良好的表达式树
我们的问题是当我们将这个表达式树转换为Linq(在EF Where子句中使用)时
我们在互联网上找到了这种转换方法:
(内部异常消息)
静态私有表达式GetFilterExpression(FilterQueryOption筛选器)
{
var enumerable=enumerable.Empty().AsQueryable();
var param=表达式参数(typeof(Countries));
if(过滤器!=null)
{
enumerable=(IQueryable)filter.ApplyTo(enumerable,新的ODataQuerySettings());
//例外:查询选项未绑定到任何CLR类型。只有绑定到CLR类型的查询选项才支持“ApplyTo”。
var mce=enumerable.Expression作为MethodCallExpression;
如果(mce!=null)
{
var quote=mce.Arguments[1]作为一元表达式;
如果(引号!=null)
{
返回quote.Operand作为表达式;
}
}
}
返回表达式.Lambda(表达式.Constant(true),param);
}
有人能帮忙吗?就像在评论中说的,我需要使用typeof(Countries)
来构建ODataQueryContext
之后抛出的异常是“TestApiRest.Countries not found”
因此,我打开了edmx文件属性并更改了名称空间以匹配我的项目名称空间
(这是TestApiRest模型,我将其更改为TestApiRest)
这是我的ODataFilterConverter
类,它与我的第一个小测试一起工作:odataString=“Id eq 2”
公共类ODataFilterConverter
{
私有只读IEDMM模型m_模型;
公共ODataFilterConverter(TestRestApiEntities db)
{
m_model=db.GetEdm();//*Breeze实验室:EdmBuilder*
}
公共表达式转换(字符串转换)
{
var filterQueryOption=GetFilterQueryOption(GetQueryContext(),odataString);
返回GetFilterExpression(filterQueryOption);
}
私有ODataQueryContext GetQueryContext()
{
返回新的ODataQueryContext(m_model,typeof(T));
}
私有筛选器查询选项GetFilterQueryOption(ODataQueryContext queryContext,字符串筛选器)
{
返回新的FilterQueryOption(filter,queryContext);
}
静态私有表达式GetFilterExpression(FilterQueryOption筛选器)
{
var enumerable=enumerable.Empty().AsQueryable();
var param=表达式参数(typeof(T));
if(过滤器!=null)
{
enumerable=(IQueryable)filter.ApplyTo(enumerable,新的ODataQuerySettings());
var mce=enumerable.Expression作为MethodCallExpression;
如果(mce!=null)
{
var quote=mce.Arguments[1]作为一元表达式;
如果(引号!=null)
{
返回quote.Operand作为表达式;
}
}
}
返回表达式.Lambda(表达式.Constant(true),param);
}
}
问题不在于过滤器查询选项
edm模型未正确映射实体。尝试将GetQueryContext
中的第3行更改为使用typeof(Country)而不是IEdmEntityType。这不适用于OData V4
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);
}
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);
}
}