【问题标题】:LINQ vb.net groupby on multiple columns with aggregate information多列上的 LINQ vb.net groupby 聚合信息
【发布时间】:2015-05-18 22:32:52
【问题描述】:

我有以下 linq 查询:

(From document In DocumentEntities
 Group Join transactionRow In TransactionEntities.Where(Function(tran) tran.PaymentType = "Charge" And tran.Amount <> 0 And (Not tran.Void.HasValue OrElse (tran.Void.HasValue AndAlso Not tran.Void.Value)))
     On document.DocumentId Equals transactionRow.DocumentId
     Into foundTransactions = Group
     From foundTransaction In foundTransactions.DefaultIfEmpty()
  Group Join documentInstrument In DocumentInstrumentEntities.Where(Function(docInst) docInst.IsPrimary)
      On document.DocumentId Equals documentInstrument.DocumentId
      Into relatedDocumentInstruments = Group
  From documentInstrument In relatedDocumentInstruments.DefaultIfEmpty()
  Join instrument In InstrumentEntities
      On documentInstrument.InstrumentId Equals instrument.InstrumentId
Where (document.DocumentId = 241083 OR document.DocumentId = 241084 OR     document.DocumentId = 241085 OR document.DocumentId = 241086 OR     document.DocumentId = 241087 OR document.DocumentId = 241090 OR     document.DocumentId = 241091 OR document.DocumentId = 241092 OR document.DocumentId = 241093 OR document.DocumentId = 241094 OR document.DocumentId = 241095 OR document.DocumentId = 241096 OR document.DocumentId = 241097 OR document.DocumentId = 241098 OR document.DocumentId = 241099 OR document.DocumentId = 241100 OR document.DocumentId = 241101 OR document.DocumentId = 241088 OR document.DocumentId = 241089)
Order By instrument.Name
Select New With
{
 .Amount = foundTransaction.Amount,
 .Code = instrument.Code,
 .Instrument = instrument.Name,
 .InstrumentId = instrument.InstrumentId,
 .Pages = document.Pages
}).GroupBy(Function(instrument) new with {instrument.Code,     instrument.Instrument})
.Select(Function(grouping) new with {.Code = grouping.Key.Code, .Instrument = grouping.Key.Instrument})

这给了我一个很好的、按 Instrument.name 排序的工具和代码的分组列表。现在我需要知道如何访问实际分组中的项目来执行聚合函数。例如,我希望在最终结果中返回 SUM(amount),但我不确定如何访问每个键的实际 IGrouping,以便获得所需的聚合。

所以,例如,我希望我的新 FINAL 选择看起来像这样:

.Select(Function(grouping) new with {.Code = grouping.Key.Code, .Instrument = grouping.Key.Instrument, .Amount = SUM(grouping.amount)}) 

我知道聚合函数中会有一个 lambda,但我只是伪代码,所以我可以尝试解释我所追求的。

感谢您的帮助!

【问题讨论】:

    标签: vb.net linq


    【解决方案1】:

    组是一个序列。 所以,试试吧:

    .Amount = grouping.Sum(Function(item) item.Amount)
    

    【讨论】:

    • 是的,我也是这么想的,我试过了,但我得到了以下错误:无法将类型 'System.Linq.IGrouping 转换为类型 system.collections.IEnumerable。使用 LinqPad
    • 我怀疑你的错误信息有更多细节,因为IGrouping&lt;T,U&gt; extends IEnumerable&lt;U&gt;
    【解决方案2】:

    发布的建议是正确的语法,我尝试过但遇到了异常,所以我需要在 groupby 之后调用 .ToList() 。

    这是有效的查询:

    (From document In DocumentEntities
     Group Join transactionRow In TransactionEntities.Where(Function(tran) tran.PaymentType = "Charge" And tran.Amount <> 0 And (Not tran.Void.HasValue OrElse (tran.Void.HasValue AndAlso Not tran.Void.Value)))
         On document.DocumentId Equals transactionRow.DocumentId
         Into foundTransactions = Group
         From foundTransaction In foundTransactions.DefaultIfEmpty()
      Group Join documentInstrument In DocumentInstrumentEntities.Where(Function(docInst) docInst.IsPrimary)
          On document.DocumentId Equals documentInstrument.DocumentId
          Into relatedDocumentInstruments = Group
      From documentInstrument In relatedDocumentInstruments.DefaultIfEmpty()
      Join instrument In InstrumentEntities
          On documentInstrument.InstrumentId Equals instrument.InstrumentId
    Where (document.DocumentId = 241083 OR document.DocumentId = 241084 OR    document.DocumentId = 241085 OR document.DocumentId = 241086 OR document.DocumentId = 241087 OR document.DocumentId = 241090 OR document.DocumentId = 241091 OR document.DocumentId = 241092 OR document.DocumentId = 241093 OR document.DocumentId = 241094 OR document.DocumentId = 241095 OR document.DocumentId = 241096 OR document.DocumentId = 241097 OR document.DocumentId = 241098 OR document.DocumentId = 241099 OR document.DocumentId = 241100 OR document.DocumentId = 241101 OR document.DocumentId = 241088 OR document.DocumentId = 241089)
    Order By instrument.Name
    Select New With
    {
     .Amount = foundTransaction.Amount,
     .Code = instrument.Code,
     .Instrument = instrument.Name,
     .InstrumentId = instrument.InstrumentId,
     .Pages = document.Pages
    }).GroupBy(Function(instrument) new with {instrument.Code,    instrument.Instrument}).ToList().Select(Function(grouping) new with {.Code = grouping.Key.Code, .Instrument = grouping.Key.Instrument, .TotalFees= grouping.Sum(Function(item) item.Amount)}).OrderBy(Function(item) item.Instrument).ThenBy(Function(item) item.Code).ToList()
    

    【讨论】:

    • 使用 ToList,您将失去 EntityFramework 在执行聚合部分的好处。从那里开始,处理数据的不是 LINQ to Entities 而是 LINQ to Object。这是一个真正的耻辱!告诉我们更多关于这个例外的信息。
    • 这里有一个例外:无法将类型 'System.Linq.IGrouping 转换为类型 system.collections.IEnumerable。
    • 在我的特定实例中,我需要将查询和 .ToList() 放入变量中,然后执行分组(短篇小说,我不需要在这里说明原因)但是分组不再适用于包含结果的本地变量。为什么会这样?
    • 所以基本上,我需要它来处理 List(Of T),而不是 Linq to Entities。该查询在 Linq to Entities 中完美运行,但不仅仅针对结果列表(来自原始查询)。
    • 不,我只需要指定键,因为 vb.net 在匿名类型上使用可变属性。所以这个工作: Dim groupedResults = tempResults.GroupBy(Function(instrument) New With { KEY instrument.Code, KEY instrument.Instrument}).ToList() -- 这工作正常。
    猜你喜欢
    • 2021-11-01
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 2020-11-05
    • 1970-01-01
    相关资源
    最近更新 更多