我有以下结果集,它是作为Linq查询的结果生成的。我想将其转换为分层结果集。前两列表示'主'行,第3列和第4列表示主行的子列表,第5列和第6列表示主行的第二子列表。包含值1971的列是连接列。
最终结果应该是一个带有容器列表(G2列)和打印机列表(G3列)的主对象。
将此转换为分层表单的查询是什么样的?
G1_ID G1_CellName G2_ContainerID G2_ID G2_SerialNumber G3_ID G3_PrinterName
1971 Default Cell 1935 1971 1101929 1971 PBG-PrtEmulator1
1971 Default Cell 1936 1971 1101930 1971 PBG-PrtEmulator1
1971 Default Cell 2189 1971 1102183 1971 PBG-PrtEmulator1
答案 0 :(得分:2)
GROUPBY?
var result = from eachData in data
group eachData by new{ eachData .G1_ID, eachData .G1_CellName }
into g1
from eachG1 in g1
group eachG1 by new { eachG1.G2_..., eachG1.G2_... }
into g2
for eachG2 in g2
group eachG2 by new { eachG2.G3_... }
into g3
select g3;
没有测试过。但我相信它看起来会像这样。
答案 1 :(得分:1)
好的,这是一个引人深思的问题。我过去做了很多数据扁平化,通常我会使用一个字典来保留所有独特的值,然后将它们结合起来。
你问过LINQ,现在我想不出单程的方式来做这个,所以我在VB中得到了这个......
Private Class FlatObj
Public Property G1_ID As Integer
Public Property G1_CellName As String
Public Property G2_ContainerID As Integer
Public Property G2_ID As Integer
Public Property G2_SerialNumber As Integer
Public Property G3_ID As Integer
Public Property G3_PrinterName As String
End Class
Private Class G1
Public Property ID As Integer
Public Property CellName As String
Public Property Containers As New List(Of G2)()
Public Property PrinterNames As New List(Of G3)()
Public Overrides Function Equals(ByVal obj As Object) As Boolean
Return ID.Equals(CType(obj, G1).ID)
End Function
Public Overrides Function GetHashCode() As Integer
Return ID.GetHashCode()
End Function
End Class
Private Class G2
Public Property fID As Integer
Public Property ContainerID As Integer
Public Property SerialNumber As Integer
Public Overrides Function Equals(ByVal obj As Object) As Boolean
Return ContainerID.Equals(CType(obj, G2).ContainerID)
End Function
Public Overrides Function GetHashCode() As Integer
Return ContainerID.GetHashCode()
End Function
End Class
Private Class G3
Public Property fID As Integer
Public Property PrinterName As String
Public Overrides Function Equals(ByVal obj As Object) As Boolean
Return PrinterName.Equals(CType(obj, G3).PrinterName)
End Function
Public Overrides Function GetHashCode() As Integer
Return PrinterName.GetHashCode()
End Function
End Class
Dim fromDb As New List(Of FlatObj) From
{
New FlatObj() With {.G1_ID = 1971, .G1_CellName = "Default Cell", .G2_ContainerID = 1935, .G2_ID = 1971, .G2_SerialNumber = 1101929, .G3_ID = 1971, .G3_PrinterName = "PBG-PrtEmulator1"},
New FlatObj() With {.G1_ID = 1971, .G1_CellName = "Default Cell", .G2_ContainerID = 1936, .G2_ID = 1971, .G2_SerialNumber = 1101930, .G3_ID = 1971, .G3_PrinterName = "PBG-PrtEmulator1"},
New FlatObj() With {.G1_ID = 1971, .G1_CellName = "Default Cell", .G2_ContainerID = 2189, .G2_ID = 1971, .G2_SerialNumber = 1102183, .G3_ID = 1971, .G3_PrinterName = "PBG-PrtEmulator1"}
}
Dim g1s = fromDb.Select(Function(x) New G1 With
{
.ID = x.G1_ID,
.CellName = x.G1_CellName
}).Distinct().ToList()
Dim g2s = fromDb.Select(Function(x) New G2 With
{
.fID = x.G2_ID,
.ContainerID = x.G2_ContainerID,
.SerialNumber = x.G2_SerialNumber
}).Distinct().ToLookup(Function(x) x.fID)
Dim g3s = fromDb.Select(Function(x) New G3 With
{
.fID = x.G3_ID,
.PrinterName = x.G3_PrinterName
}).Distinct().ToLookup(Function(x) x.fID)
g1s.ForEach(Sub(g)
g.Containers.AddRange(g2s(g.ID))
g.PrinterNames.AddRange(g3s(g.ID))
End Sub)
请注意,相当多的工作都经历了Distinct()和ToLookup()扩展。希望这会有所帮助,我想看看是否有更“LINQy”的方式:D