2010-11-29 35 views
5

Linqクエリの結果として生成された次の結果セットがあります。私はこれを階層的な結果セットに変換したいと思います。最初の2つの列は「マスター」行を表し、列3および4はマスター行の子リストを表し、列5および6はマスター行の第2子リストを表します。値1971を含む列は結合列です。Linq - フラットから階層への変換方法?

最終結果は、コンテナのリスト(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

明確にするために...オブジェクトのように見える階層を必要とします - Cell.Containers、Cell.SerialNumbers、Cell.PrinterNames(コレクションとして)でCell? – Tom

+0

このLinqはSqlに、LinqはEFに、Linqはオブジェクトに、または他の何かにありますか? –

+0

@Tom - Cell - > Cell.Containers、Cell - > PrinterNamesのような階層が必要です。シリアル番号列はコンテナのプロパティです。 –

答えて

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; 

テストしていません。しかし、私はそれがちょうどこのように見えると確信しています。

+0

私はGroupByを考えましたが、それは各g1要素にグループ化されたg2とg3データのコレクションを生成しません。私はあなたが元のリストに3回通過する必要があると思うが、多分私は間違っている:) – Tom

1

[OK]これは非常に刺激的な質問です。私は過去に多くのデータを平坦化していましたが、一般的には辞書を使ってすべてのユニークな値を保持し、後で結婚させていました。

のかなり多くいること

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) 
...お知らせをあなたは今、私はこれを行うにはシングルパス方法を考えることはできません、LINQを求めたので、私はVBで、代わりにこれを持っています仕事はDistinct()とToLookup()の拡張を行っています。これが助けてくれることを願って、もっと「LINQy」の方法があるかどうかを見たいと思います:D

関連する問題