Linq将分组表返回为数据表

Posted

技术标签:

【中文标题】Linq将分组表返回为数据表【英文标题】:Linq Return grouped Table as Datatable 【发布时间】:2014-10-02 23:08:03 【问题描述】:

我编写了一个返回 DataTable 对象的函数。对于以下代码

Public Function GetArtikelsAbove50(ByVal limit As Integer) As DataTable
    Dim query = _Set.Ten_Most_Expensive_Products.AsEnumerable.Where(Function(x) x.UnitPrice > limit) _
    .GroupBy(Function(x) x.UnitPrice)
    Return query.CopyToDataTable
End Function

query 是一个 System.Data.EnumerableRowCollection(Of SPTest.northwindDataSet.Ten_Most_Expensive_ProductsRow) 对象。代码运行,一切都很好。但如果我添加:

.GroupBy(Function(x) x.UnitPrice)

编译器为返回对象添加下划线 (query.CopyToDataTable)。查询现在是 System.Collections.Generic.IEnumerable(Of System.Linq.IGrouping(Of Decimal, SPTest.northwindDataSet.Ten_Most_Expensive_ProductsRow)) 对象,因此 CopyToDataTable 不再是其中的成员。由于我需要.GroupBy 函数(有些适用于.Sum))我正在寻找一种将它与.CopyToDataTable 结合使用的方法。这可能吗?如果可以,我该如何实现?

我想,mybe 返回一个DataView Objeckt(带有Return query.AsDataView)会起作用,但同样的错误。

提示: 在我的研究过程中,我发现在this 问题中,一位用户提到函数 .CopyToDataTable “仅限于 IEnumerable,不适用于 IEnumerable(of T)”。我对数据集不太熟悉,我不确定这是否有助于解决问题。只是想分享一下信息,也许有帮助。

【问题讨论】:

【参考方案1】:

问题是应用GroupBy 会改变你的表达方式。您的枚举现在是

的 IEnumerable
 System.Linq.IGrouping(Of Decimal, SPTest.northwindDataSet.Ten_Most_Expensive_ProductsRow)

而不仅仅是

 SPTest.northwindDataSet.Ten_Most_Expensive_ProductsRow

CopyToDataTableIEnumerable(of DataRow) 的扩展函数,因此不适用于这种新的匿名类型。

至于要做什么...好吧,要恢复函数,您需要将新类型转换为DataRowDataRow 的子类。

例如,您可以在DataSet 中创建一个具有所需行结构的新表(在本例中我们称之为NewTable),这将导致一个名为NewTableRow 的新强类型类成为生成。

然后您可以编写.Select 语句将System.Linq.IGrouping(Of Decimal, SPTest.northwindDataSet.Ten_Most_Expensive_ProductsRow) 对象转换为NewTableRow 对象。

所产生的IEnumerable(Of SPTest.northwindDataSet.NewTableRow) 实例将使CopyToDataTable 再次可用。

预计到达时间:一个例子。免责声明:这是用 C# 编写并自动翻译为 VB,因此可能存在一些怪癖。但你应该明白这一点。

' We need an instance of the the target table to access the NewRow method
Dim newTable As New NewTable 
Dim newRows = query.[Select](Function(g) ' We're using an anonymous method here, but you could make it a regular method.
  'A quirk of DataTable & DataRow: you can't just "new" up a DataRow.  You have to use the
  'NewRow or generated, strongly-typed NewXXXXRow method to get a new DataRow.
  Dim newRow = newTable.NewNewTableRow() 
  ' You can now set the properties on your new strongly-typed DataRow.
  newRow.UnitPrice = g.Key   
  newRow.Quantity = g.Sum(Function(d) d.Quantity)
  ' Don't forget to return the result!
  Return newRow
End Function)

或者,您可以使用AddNewTableRow 方法创建新行并将其添加到目标表。你甚至不需要使用CopyToDataTable

【讨论】:

你好安,谢谢你的回答。关于上一节之前的部分:您能否给我更多关于如何使用 .Select 语句将我的对象转换为 NewTableRow 对象的信息? 太棒了!非常感谢您的回答!

以上是关于Linq将分组表返回为数据表的主要内容,如果未能解决你的问题,请参考以下文章

Linq to SQL -- Group ByHaving和ExistsInAnyAllContains

LINQ to SQL语句之Group By/Having

Linq,EF Core - 按一个字段分组并使用其他字段从其他表中获取数据列表

使用linq在mvc5中按外键表分组表

实体框架 LINQ - 具有分组依据的子查询

如何使用linq按多列分组[重复]