2

我有一些 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();

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

现在,我想向这个 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”是红色下划线的,编译器报错“An expression tree may not contain an assignment operator”

任何人都能够解释这意味着什么,以及我如何解决它?我已经进行了一些搜索,但找不到问题所在。我尝试阅读表达式树,但无法真正弄清楚它们是什么,这可能是问题所在。

我在这个项目的其他地方做了完全相同的事情,但那是使用内存中的集合,而不是使用 Linq to Entities 的集合,这可能是不同的。

4

3 回答 3

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 中运行良好(事实上,我几乎可以肯定您会看到运行时错误),但它应该可以帮助您克服编译问题。

从 .NET 4.0 开始,您可以使用string.Joinwith 方法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带入记忆。

于 2013-07-15T14:33:04.833 回答
1

+=就行是这样的.Aggregate(s1 = s1 + "|"。您实际上是要更改 的值s1吗?如果没有,只需使用s1 + "|" + a.

于 2013-07-15T14:31:21.037 回答
0

好的,好吧,这似乎无法做到。想一想,是有道理的,因为你不能在SQL中做Aggregate的等价物,所以L2E不能翻译它。

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

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

希望这可以帮助某人。感谢那些回答的人。

于 2013-07-15T16:38:01.030 回答