3

为什么我得到:

方法“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>
4

3 回答 3

2

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

于 2013-04-23T17:11:37.133 回答
0

为什么不直接移动投影之前的位置?这将导致执行过滤器和项目的单个查询:

XrmServiceContext.CreateQuery<Contact>().Where(p => p.FirstName == "John").Project().To<Person>().First();
于 2013-04-23T18:13:30.423 回答
0

查看AutoMapper 对 QueryableExtensions 的说明,它有一个示例显示投影之前的 Where 子句。您需要重构代码以支持此模型,而不是将Where子句放在投影之后。

公共列表 GetLinesForOrder(int orderId)
{
  映射器.CreateMap()
    .ForMember(dto => dto.Item, conf => conf.MapFrom(ol => ol.Item.Name);

  使用 (var context = new orderEntities())
  {
    返回 context.OrderLines.Where(ol => ol.OrderId == orderId)
             .Project().To().ToList();
  }
}

鉴于 Dynamic CRM 的 LINQ 提供程序的限制,您不应期望 AutoMapper 一定会正确获取 LINQ 查询。

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

于 2013-04-24T00:47:40.717 回答