从FilterQueryOption获取Linq表达式抛出CLR异常

时间:2014-09-04 14:40:06

标签: c# linq odata entity-framework-6 linq-expressions

我们有一个基于OData conventions

的过滤字符串

我们需要解析这个字符串,并在我们的EntityFramework6 Model-First生成的模型上执行whereClause。

步骤:

  1. 使用Breeze EdmBuilder nuget包将我们的DataModel DbContext转换为IEdmlModel
  2. 使用此ODataQueryContext创建EdmModel
  3. 使用FilterQueryOption和过滤字符串创建ODataQueryContext
  4. 此时,我们有一个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)

    有人可以为此提供帮助吗?

1 个答案:

答案 0 :(得分:0)

Chad Carisch在评论中说的一样,我需要使用typeof(Countries)来构建ODataQueryContext

之后抛出的异常是&#34; TestApiRest.Countries not found &#34;。

所以我打开edmx文件属性并更改了命名空间以匹配我的项目命名空间 (这是TestApiRestModel,我将其更改为TestApiRest)

这是我的ODataFilterConverter课程,适用于我的第一个小测试:odataString =&#34; Id eq 2&#34;

  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);
    }
  }