“Where”方法不能遵循“选择”方法或不支持

时间:2013-04-23 16:18:01

标签: c# linq dynamics-crm-2011 automapper iqueryable

为什么我会:

  

方法'Where'不能遵循'Select'方法或不是   支持的。尝试根据支持的方法或调用编写查询   调用不支持之前的'AsEnumerable'或'ToList'方法   方法

...使用WHERE子句时,比如调用时:

XrmServiceContext.CreateQuery<Contact>().Project().To<Person>().Where(p => p.FirstName == "John").First();

这有效:

XrmServiceContext.CreateQuery<Contact>().Project().To<Person>().First();

这也有效:

XrmServiceContext.CreateQuery<Contact>().Where(p => p.FirstName == "John").First();

我正在使用AutoMapper QueryableExtension

其他信息:

  • 我不想在Where子句之前调用ToList()。我知道它会那样有效。
  • CreateQuery<TEntity>()返回IQueryable<TEntity>

3 个答案:

答案 0 :(得分:2)

这是因为您使用的任何查询提供程序都无法处理此问题。在一般情况下,它不是无效的;事实上,大多数查询提供者支持过滤后的过滤。某些查询提供程序不像其他查询提供程序那样健壮,或者它们表示的查询模型不如LINQ接口(或两者)灵活/强大。因此,从C#编译器的角度来看,LINQ操作可能仍然无法由查询提供程序进行翻译,因此它能做的最好就是在运行时抛出异常。

答案 1 :(得分:0)

为什么不在投影前移动它所在的位置?它将导致执行一个过滤和项目的单个查询:

XrmServiceContext.CreateQuery<Contact>().Where(p => p.FirstName == "John").Project().To<Person>().First();

答案 2 :(得分:0)

查看AutoMapper's instructions for the QueryableExtensions它有一个示例,显示投影前的Where子句。您需要重构代码以支持此模型,而不是在投影后放置Where子句。

public List GetLinesForOrder(int orderId)
{
  Mapper.CreateMap()
    .ForMember(dto => dto.Item, conf => conf.MapFrom(ol => ol.Item.Name);

  using (var context = new orderEntities())
  {
    return context.OrderLines.Where(ol => ol.OrderId == orderId)
             .Project().To().ToList();
  }
}

鉴于Dynamic CRM的LINQ提供程序的局限性,您不应期望AutoMapper必须正确获取LINQ查询。

这种设计背后有一个逻辑。作为开发人员,您可以创建一个有效的Where子句。然后,让AutoMapper的Project().To()定义select语句。由于CRM的LINQ提供程序支持匿名类型,因此它应该可以正常工作。 AutoMapper中投影的目的是将从每个类检索的数据限制为仅投影到类所需的数据。它不打算基于预计的类来编写Where子句。