이 질문에없는 하나의 간단한 답이있다 그러나 당신이 더 사소한하기 위해 할 수있는 일이 있습니다. 다음 코드는 다음 데이터 스키마를 기반으로합니다.
데이터 스키마를 반영한 맞춤 클래스를 만드는 것이 가장 먼저해야 할 일입니다.
다음으로 확장/도우미 메서드를 두 개 만들어야합니다. (당신은이 게시물 하단의 전체 소스 코드를 찾을 수 있습니다.)
<Extension()>
Public Function ToList(Of T As {Class, New})(source As DataTable) As List(Of T)
사용은
는 목록으로 DataTable을
Dim [set] As DataSet = ReadXmlIntoDataSet()
"변환"테이블에 XML 파일을 읽어보십시오.
Dim authors As List(Of Author) = [set].Tables("authors").ToList(Of Author)()
Dim books As List(Of Book) = [set].Tables("books").ToList(Of Book)()
Dim reviews As List(Of Review) = [set].Tables("reviews").ToList(Of Review)()
사용 LINQ는 목록에 가입 한 후 DataTable을 다시 결과를 "변환"합니다.
Dim results As DataTable = (
From a In authors
From b In books.Where(Function(item) ((Not a Is Nothing) AndAlso item.fk_author = a.pk_author)).DefaultIfEmpty()
From r In reviews.Where(Function(item) ((Not b Is Nothing) AndAlso item.fk_book = b.pk_book)).DefaultIfEmpty()
Select New With {
.pk_author = If((Not a Is Nothing), New Integer?(a.pk_author), Nothing),
.pk_book = If((Not b Is Nothing), New Integer?(b.pk_book), Nothing),
.pk_review = If((Not r Is Nothing), New Integer?(r.pk_review), Nothing),
.firstname = If((Not a Is Nothing), a.firstname, Nothing),
.lastname = If((Not a Is Nothing), a.lastname, Nothing),
.title = If((Not b Is Nothing), b.title, Nothing),
.[text] = If((Not r Is Nothing), r.[text], Nothing)
}
).ToList().ToDataTable()
소스 코드
참조
Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Reflection
Imports <your namespace goes here>.Extensions
저자
0 1,238,864, 예약
Public Class Book
Public Property pk_book As Integer
Public Property fk_author As Integer
Public Property title As String
End Class
검토
Public Class Review
Public Property pk_review As Integer
Public Property fk_book As Integer
Public Property [text] As String
End Class
확장
<Extension()>
Public Module Extensions
<Extension()>
Public Function ToDataTable(Of T)(source As List(Of T)) As DataTable
Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
Dim table As New DataTable()
Dim descriptor As PropertyDescriptor = Nothing
Dim column As DataColumn = Nothing
Dim values As Object() = Nothing
Dim length As Integer = Nothing
Dim index As Integer = Nothing
Dim item As T = Nothing
Dim type As Type = Nothing
table.BeginInit()
For Each descriptor In properties
type = Nullable.GetUnderlyingType(descriptor.PropertyType)
column = New DataColumn()
column.ColumnName = descriptor.Name
column.Caption = descriptor.DisplayName
column.DataType = If((type Is Nothing), descriptor.PropertyType, type)
column.ReadOnly = descriptor.IsReadOnly
table.Columns.Add(column)
Next
table.BeginLoadData()
length = (properties.Count - 1)
values = New Object(length) {}
For Each item In source
For index = 0 To length
values(index) = properties(index).GetValue(item)
Next
table.Rows.Add(values)
Next
table.EndLoadData()
table.EndInit()
Return table
End Function
<Extension()>
Public Function ToList(Of T As {Class, New})(source As DataTable) As List(Of T)
If (source Is Nothing) Then
Throw New ArgumentNullException("source")
End If
Dim list As New List(Of T)
Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
Dim descriptor As PropertyDescriptor = Nothing
Dim index As Integer = Nothing
Dim row As DataRow = Nothing
Dim item As T = Nothing
For index = (properties.Count - 1) To 0 Step -1
If (Not source.Columns.Contains(properties(index).Name)) Then
properties.RemoveAt(index)
End If
Next
For Each row In source.Rows
item = New T()
For Each descriptor In properties
descriptor.SetValue(item, row.Item(descriptor.Name))
Next
list.Add(item)
Next
Return list
End Function
End Module
S 충분한 신청
Public Class Form1
Public Sub New()
Me.InitializeControls()
Try
Dim [set] As DataSet = Form1.ReadXmlIntoDataSet()
Dim authors As List(Of Author) = [set].Tables("authors").ToList(Of Author)()
Dim books As List(Of Book) = [set].Tables("books").ToList(Of Book)()
Dim reviews As List(Of Review) = [set].Tables("reviews").ToList(Of Review)()
Dim results As DataTable = (
From a In authors
From b In books.Where(Function(item) ((Not a Is Nothing) AndAlso item.fk_author = a.pk_author)).DefaultIfEmpty()
From r In reviews.Where(Function(item) ((Not b Is Nothing) AndAlso item.fk_book = b.pk_book)).DefaultIfEmpty()
Select New With {
.pk_author = If((Not a Is Nothing), New Integer?(a.pk_author), Nothing),
.pk_book = If((Not b Is Nothing), New Integer?(b.pk_book), Nothing),
.pk_review = If((Not r Is Nothing), New Integer?(r.pk_review), Nothing),
.firstname = If((Not a Is Nothing), a.firstname, Nothing),
.lastname = If((Not a Is Nothing), a.lastname, Nothing),
.title = If((Not b Is Nothing), b.title, Nothing),
.[text] = If((Not r Is Nothing), r.[text], Nothing)
}
).ToList().ToDataTable()
Me.resultsGrid.DataSource = results
Me.authorsGrid.DataSource = authors
Me.booksGrid.DataSource = books
Me.reviewsGrid.DataSource = reviews
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Private Sub InitializeControls()
Me.Label1 = New System.Windows.Forms.Label() With {.AutoSize = True, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 213), .Name = "Label1", .Size = New System.Drawing.Size(60, 18), .TabIndex = 0, .Text = "Reviews"}
Me.Label2 = New System.Windows.Forms.Label() With {.AutoSize = True, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 142), .Name = "Label2", .Size = New System.Drawing.Size(45, 18), .TabIndex = 4, .Text = "Books"}
Me.Label3 = New System.Windows.Forms.Label() With {.AutoSize = True, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 71), .Name = "Label3", .Size = New System.Drawing.Size(57, 18), .TabIndex = 7, .Text = "Authors"}
Me.Label4 = New System.Windows.Forms.Label() With {.AutoSize = True, .Dock = System.Windows.Forms.DockStyle.Top, .Font = New System.Drawing.Font("Calibri", 9.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte)), .Location = New System.Drawing.Point(0, 0), .Name = "Label4", .Size = New System.Drawing.Size(51, 18), .TabIndex = 10, .Text = "Result:"}
Me.Splitter1 = New System.Windows.Forms.Splitter() With {.BackColor = System.Drawing.Color.Gray, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 203), .Name = "Splitter1", .Size = New System.Drawing.Size(613, 10), .TabIndex = 2, .TabStop = False}
Me.Splitter2 = New System.Windows.Forms.Splitter() With {.BackColor = System.Drawing.Color.Gray, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 132), .Name = "Splitter2", .Size = New System.Drawing.Size(613, 10), .TabIndex = 5, .TabStop = False}
Me.Splitter3 = New System.Windows.Forms.Splitter() With {.BackColor = System.Drawing.Color.Gray, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 61), .Name = "Splitter3", .Size = New System.Drawing.Size(613, 10), .TabIndex = 8, .TabStop = False}
Me.resultsGrid = New System.Windows.Forms.DataGridView() With {.AllowUserToAddRows = False, .AllowUserToDeleteRows = False, .BackgroundColor = System.Drawing.Color.White, .ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 18), .Name = "resultsGrid", .ReadOnly = True, .Size = New System.Drawing.Size(613, 280), .TabIndex = 9}
Me.authorsGrid = New System.Windows.Forms.DataGridView() With {.AllowUserToAddRows = False, .AllowUserToDeleteRows = False, .BackgroundColor = System.Drawing.Color.White, .ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 89), .Name = "authorsGrid", .ReadOnly = True, .Size = New System.Drawing.Size(613, 115), .TabIndex = 6}
Me.booksGrid = New System.Windows.Forms.DataGridView() With {.AllowUserToAddRows = False, .AllowUserToDeleteRows = False, .BackgroundColor = System.Drawing.Color.White, .ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize, .Dock = System.Windows.Forms.DockStyle.Top, .Location = New System.Drawing.Point(0, 160), .Name = "booksGrid", .ReadOnly = True, .Size = New System.Drawing.Size(613, 200), .TabIndex = 3}
Me.reviewsGrid = New System.Windows.Forms.DataGridView() With {.AllowUserToAddRows = False, .AllowUserToDeleteRows = False, .BackgroundColor = System.Drawing.Color.White, .ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize, .Dock = System.Windows.Forms.DockStyle.Fill, .Location = New System.Drawing.Point(0, 231), .Name = "reviewsGrid", .ReadOnly = True, .Size = New System.Drawing.Size(613, 415), .TabIndex = 1}
Me.SuspendLayout()
Me.AutoScaleDimensions = New System.Drawing.SizeF(8.0!, 18.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(613, 900)
Me.Controls.AddRange({Me.reviewsGrid, Me.Label1, Me.Splitter1, Me.booksGrid, Me.Label2, Me.Splitter2, Me.authorsGrid, Me.Label3, Me.Splitter3, Me.resultsGrid, Me.Label4})
Me.Font = New System.Drawing.Font("Calibri", 9.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.Margin = New System.Windows.Forms.Padding(3, 4, 3, 4)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Private Shared Function ReadXmlIntoDataSet() As DataSet
Dim [set] As New DataSet()
Dim authors As DataTable = [set].Tables.Add("authors")
With authors
.Columns.Add("pk_author", GetType(Integer))
.Columns.Add("firstname", GetType(String))
.Columns.Add("lastname", GetType(String))
.BeginLoadData()
.Rows.Add(1, "William", "Shakespeare")
.Rows.Add(2, "Henrik", "Ibsen")
.Rows.Add(3, "Ernest", "Hemingway")
.EndLoadData()
.AcceptChanges()
End With
Dim books As DataTable = [set].Tables.Add("books")
With books
.Columns.Add("pk_book", GetType(Integer))
.Columns.Add("fk_author", GetType(Integer))
.Columns.Add("title", GetType(String))
.BeginLoadData()
.Rows.Add(1, 1, "Timon of Athens")
.Rows.Add(2, 1, "Titus Othello")
.Rows.Add(3, 1, "The Comedy of Errors")
.Rows.Add(4, 2, "Peer Gynt")
.Rows.Add(5, 2, "A Doll's House")
.Rows.Add(6, 2, "Emperor and Galilean")
.EndLoadData()
.AcceptChanges()
End With
Dim reviews As DataTable = [set].Tables.Add("reviews")
With reviews
.Columns.Add("pk_review", GetType(Integer))
.Columns.Add("fk_book", GetType(Integer))
.Columns.Add("text", GetType(String))
.BeginLoadData()
.Rows.Add(1, 1, "The book 'Timon of Athens' blabla ...")
.Rows.Add(2, 2, "The book 'Titus Othello' blabla ...")
.Rows.Add(3, 4, "The book 'Peer Gynt' blabla 1...")
.Rows.Add(4, 4, "The book 'Peer Gynt' blabla 2...")
.Rows.Add(5, 4, "The book 'Peer Gynt' blabla 3...")
.Rows.Add(6, 5, "The book 'A Doll's House' blabla ...")
.EndLoadData()
.AcceptChanges()
End With
[set].Relations.Add(New DataRelation("books_author", authors.Columns("pk_author"), books.Columns("fk_author")))
[set].Relations.Add(New DataRelation("reviews_books", books.Columns("pk_book"), reviews.Columns("fk_book")))
Return [set]
End Function
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents Label3 As System.Windows.Forms.Label
Friend WithEvents Label4 As System.Windows.Forms.Label
Friend WithEvents Splitter1 As System.Windows.Forms.Splitter
Friend WithEvents Splitter2 As System.Windows.Forms.Splitter
Friend WithEvents Splitter3 As System.Windows.Forms.Splitter
Friend WithEvents resultsGrid As System.Windows.Forms.DataGridView
Friend WithEvents authorsGrid As System.Windows.Forms.DataGridView
Friend WithEvents booksGrid As System.Windows.Forms.DataGridView
Friend WithEvents reviewsGrid As System.Windows.Forms.DataGridView
End Class
어떤 제안? – smr5