次の方法で共有


方法: 複数のソースからオブジェクト コレクションを設定する (LINQ) (Visual Basic)

この例では、さまざまなソースのデータを新しい型のシーケンスにマージする方法を示します。

メモリ内のデータやファイル システム内のデータを、データベース内のデータと結合しないでください。 このようなクロスドメイン結合では、データベース クエリやその他の種類のソースに対して結合操作を定義する方法が異なるため、未定義の結果が得られる可能性があります。 さらに、データベース内のデータ量が十分に大きい場合、このような操作によってメモリ不足の例外が発生する可能性があります。 データベースからメモリ内データにデータを結合するには、最初にデータベース クエリで ToList または ToArray を呼び出し、返されたコレクションで結合を実行します。

データ ファイルを作成するには

次の例では、名前付き型 Student を使用して、スプレッドシート データを .csv 形式でシミュレートする 2 つのメモリ内の文字列コレクションからマージされたデータを格納する方法を示します。 文字列の最初のコレクションは学生の名前と ID を表し、2 番目のコレクションは学生 ID (最初の列) と 4 つの試験スコアを表します。 ID は外部キーとして使用されます。

Imports System.Collections.Generic
Imports System.Linq

Class Student
    Public FirstName As String
    Public LastName As String
    Public ID As Integer
    Public ExamScores As List(Of Integer)
End Class

Class PopulateCollection

    Shared Sub Main()

        ' Merge content from spreadsheets into a list of Student objects.

        ' These data files are defined in How to: Join Content from
        ' Dissimilar Files (LINQ).

        ' Each line of names.csv consists of a last name, a first name, and an
        ' ID number, separated by commas. For example, Omelchenko,Svetlana,111
        Dim names As String() = System.IO.File.ReadAllLines("../../../names.csv")

        ' Each line of scores.csv consists of an ID number and four test
        ' scores, separated by commas. For example, 111, 97, 92, 81, 60
        Dim scores As String() = System.IO.File.ReadAllLines("../../../scores.csv")

        ' The following query merges the content of two dissimilar spreadsheets
        ' based on common ID values.
        ' Multiple From clauses are used instead of a Join clause
        ' in order to store the results of scoreLine.Split.
        ' Note the dynamic creation of a list of integers for the
        ' ExamScores member. The first item is skipped in the split string
        ' because it is the student ID, not an exam score.
        Dim queryNamesScores = From nameLine In names
                          Let splitName = nameLine.Split(New Char() {","})
                          From scoreLine In scores
                          Let splitScoreLine = scoreLine.Split(New Char() {","})
                          Where Convert.ToInt32(splitName(2)) = Convert.ToInt32(splitScoreLine(0))
                          Select New Student() With {
                               .FirstName = splitName(1), .LastName = splitName(0), .ID = splitName(2),
                               .ExamScores = (From scoreAsText In splitScoreLine Skip 1
                                             Select Convert.ToInt32(scoreAsText)).ToList()}

        ' Optional. Store the query results for faster access in future
        ' queries. This could be useful with very large data files.
        Dim students As List(Of Student) = queryNamesScores.ToList()

        ' Display each student's name and exam score average.
        For Each s In students
            Console.WriteLine("The average score of " & s.FirstName & " " &
                              s.LastName & " is " & s.ExamScores.Average())
        Next

        ' Keep console window open in debug mode.
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub
End Class

' Output:
' The average score of Svetlana Omelchenko is 82.5
' The average score of Claire O'Donnell is 72.25
' The average score of Sven Mortensen is 84.5
' The average score of Cesar Garcia is 88.25
' The average score of Debra Garcia is 67
' The average score of Fadi Fakhouri is 92.25
' The average score of Hanying Feng is 88
' The average score of Hugo Garcia is 85.75
' The average score of Lance Tucker is 81.75
' The average score of Terry Adams is 85.25
' The average score of Eugene Zabokritski is 83
' The average score of Michael Tucker is 92

Select Clause 句では、オブジェクト初期化子を使用して、2 つのソースのデータを使用して新しいStudent オブジェクトをインスタンス化します。

クエリの結果を格納する必要がない場合は、名前付き型よりも匿名型の方が便利です。 クエリを実行するメソッドの外部でクエリ結果を渡す場合は、名前付き型が必要です。 次の例では、前の例と同じタスクを実行しますが、名前付き型ではなく匿名型を使用します。

' Merge the data by using an anonymous type.
' Note the dynamic creation of a list of integers for the
' ExamScores member. We skip 1 because the first string
' in the array is the student ID, not an exam score.
Dim queryNamesScores2 =
    From nameLine In names
    Let splitName = nameLine.Split(New Char() {","})
    From scoreLine In scores
    Let splitScoreLine = scoreLine.Split(New Char() {","})
    Where Convert.ToInt32(splitName(2)) = Convert.ToInt32(splitScoreLine(0))
    Select New With
           {.Last = splitName(0),
            .First = splitName(1),
            .ExamScores = (From scoreAsText In splitScoreLine Skip 1
                           Select Convert.ToInt32(scoreAsText)).ToList()}

' Display each student's name and exam score average.
For Each s In queryNamesScores2
    Console.WriteLine("The average score of " & s.First & " " &
                      s.Last & " is " & s.ExamScores.Average())
Next

こちらも参照ください