“表达式树可能不包含赋值运算符”在Select子句中使用Aggregate

时间:2013-07-15 14:26:20

标签: c# linq linq-to-entities aggregate

我有一些Linq to Entities代码从商店中提取数据并从中创建DTO集合......

  List<VRTSystemOverview> systems = query.OrderBy(s => s.DHRNumber)
    .Select(s => new VRTSystemOverview {
      ID = s.ID,
      SystemNumber = s.SystemNumber
      // other properties removed for clarity...
    })
    .ToList();

query是一个非枚举查询,基于当前上下文,并应用了一些过滤。

现在,我想向此DTO添加一个新属性,该属性是一个以管道分隔的字符串,由原始系统对象上的子属性的代码组成。这用于在客户端上进行过滤。

导航工作原理如下,每个系统都有产品配置,每个产品配置都有许多价目表条目,每个条目都有一个代码。因此,我认为我应该能够做到以下几点......

  List<VRTSystemOverview> systems = vrtSystemsBasicQuery.OrderBy(s => s.DHRNumber)
    .Select(s => new VRTSystemOverview {
      ID = s.ID,
      SystemNumber = s.SystemNumber,
      PriceBookCodes = s.ProductConfiguration
        .ProductConfigurations_PriceBook
        .Select(pb => pb.PriceBook.ProductCode)
        .Aggregate("", (s1, a) => s1 += "|" + a)
    })
    .ToList();

但是,Aggregate方法中的第二个“s1”以红色下划线,编译器给出错误“表达式树可能不包含赋值运算符”

任何人都能解释这意味着什么,以及我如何解决这个问题?我做了一些搜索,但找不到问题所在。我尝试阅读表达树,但无法确定它们是什么,这可能是问题所在。

我在这个项目的其他地方完成了同样的工作,但那是在使用内存中的集合,而不是使用Linq to Entities,这可能是不同的。

3 个答案:

答案 0 :(得分:2)

您的聚合不应该分配值,它应该返回总和的值:

List<VRTSystemOverview> systems = vrtSystemsBasicQuery.OrderBy(s => s.DHRNumber)
 .Select(s => new VRTSystemOverview {
   ID = s.ID,
  SystemNumber = s.SystemNumber,
  PriceBookCodes = s.ProductConfiguration
    .ProductConfigurations_PriceBook
    .Select(pb => pb.PriceBook.ProductCode)
    .Aggregate("", (s1, a) => s1 + "|" + a)
 })
.ToList();

我不确定这是否能在EF中运行良好(事实上,我几乎肯定你会看到运行时错误),但它应该可以帮助你克服编译问题。< / p>

从.NET 4.0开始,您可以将string.Join方法与IEnumerable<T>一起使用,如下所示:

List<VRTSystemOverview> systems = vrtSystemsBasicQuery.OrderBy(s => s.DHRNumber)
 .Select(s => new VRTSystemOverview {
   ID = s.ID,
  SystemNumber = s.SystemNumber,
  PriceBookCodes = s.ProductConfiguration
    .ProductConfigurations_PriceBook
    .Select(pb => string.Join("|", pb.PriceBook.ProductCode))
 })
.ToList();

这应该适用于内存操作。

要解决运行时错误,请尝试以下操作:

List<VRTSystemOverview> systems = vrtSystemsBasicQuery.OrderBy(s => s.DHRNumber)
 .Select(s => new VRTSystemOverview {
   ID = s.ID,
   SystemNumber = s.SystemNumber,
   PriceBookCodeList = s.ProductConfiguration
    .ProductConfigurations_PriceBook
    .Select(pb => pb.PriceBook.ProductCode)
    .ToList()
 })
.AsEnumerable()
.Select(s => new {
    ID = s.ID,
    SystemNumber = s.SystemNumber,
    PriceBookCodes = string.Join("|", s.PriceBookCodeList)
});

我们的想法是将string的形成带入记忆中。

答案 1 :(得分:1)

+=行上的.Aggregate(就像:s1 = s1 + "|"。你真的想改变s1的价值吗?如果没有,请使用s1 + "|" + a

答案 2 :(得分:0)

好的,好吧,似乎无法做到这一点。考虑到它,这是有道理的,因为你不能在SQL中做相当的聚合,所以L2E无法翻译它。

我在类似问题right here on SO中找到了帮助,特别是那里的建议(来自adrift)创建包含所需数据的匿名类型,然后枚举查询,最后(当我们'重新处理内存中的集合,所以使用Linq To Objects进行聚合。

这工作正常,但将查询的执行时间增加了十倍!我决定在主DTO上添加价格手册代码作为子集合,这是快速而简单的,然后在客户端中过滤集合。这使得发送到客户端的数据略大,但会降低查询执行速度。

希望这有助于某人。感谢那些回复的人。