LINQ によるデータ変換 (C#)
統合言語クエリ (LINQ) で行うことができるのは、データの取得だけではありません。 データ変換のための強力なツールとしても使用できます。 LINQ クエリを使用することにより、ソース シーケンスを入力として使用し、さまざまな方法で加工して新しい出力シーケンスを作成できます。 並べ替えやグループ化を行うと、要素自体は変更せずに、シーケンス自体を変更できます。しかし、LINQ クエリの最も強力な機能は、新しい型を作成できることにあると言えます。 これは select 句によって実現されます。 たとえば、次のタスクを実行できます。
複数の入力シーケンスを結合して、新しい型の単一の出力シーケンスを作成する。
ソース シーケンス内の各要素のプロパティの 1 つまたは一部だけで構成される要素から出力シーケンスを作成する。
ソース データに対して操作を実行し、その結果で構成される要素から出力シーケンスを作成する。
別の形式で出力シーケンスを作成する。 たとえば、SQL の行またはテキスト ファイルのデータを XML に変換できます。
これらはほんの一例です。 これらの変換を、同じクエリ内でさまざまな方法で組み合わせて使用することもできます。 また、あるクエリの出力シーケンスを別のクエリの入力シーケンスとして使用することもできます。
複数の入力を 1 つの出力シーケンスに結合する
LINQ クエリを使用して、複数の入力シーケンスの要素を含む 1 つの出力シーケンスを作成できます。 次の例は、2 つのインメモリ データ構造を結合する方法を示していますが、ソースが XML、SQL、または DataSet のデータを結合する場合も、同じ基本原則を適用できます。 次の 2 つのクラス型があるとします。
class Student
{
public string First { get; set; }
public string Last {get; set;}
public int ID { get; set; }
public string Street { get; set; }
public string City { get; set; }
public List<int> Scores;
}
class Teacher
{
public string First { get; set; }
public string Last { get; set; }
public int ID { get; set; }
public string City { get; set; }
}
クエリの例を次に示します。
class DataTransformations
{
static void Main()
{
// Create the first data source.
List<Student> students = new List<Student>()
{
new Student {First="Svetlana",
Last="Omelchenko",
ID=111,
Street="123 Main Street",
City="Seattle",
Scores= new List<int> {97, 92, 81, 60}},
new Student {First="Claire",
Last="O’Donnell",
ID=112,
Street="124 Main Street",
City="Redmond",
Scores= new List<int> {75, 84, 91, 39}},
new Student {First="Sven",
Last="Mortensen",
ID=113,
Street="125 Main Street",
City="Lake City",
Scores= new List<int> {88, 94, 65, 91}},
};
// Create the second data source.
List<Teacher> teachers = new List<Teacher>()
{
new Teacher {First="Ann", Last="Beebe", ID=945, City = "Seattle"},
new Teacher {First="Alex", Last="Robinson", ID=956, City = "Redmond"},
new Teacher {First="Michiyo", Last="Sato", ID=972, City = "Tacoma"}
};
// Create the query.
var peopleInSeattle = (from student in students
where student.City == "Seattle"
select student.Last)
.Concat(from teacher in teachers
where teacher.City == "Seattle"
select teacher.Last);
Console.WriteLine("The following students and teachers live in Seattle:");
// Execute the query.
foreach (var person in peopleInSeattle)
{
Console.WriteLine(person);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
The following students and teachers live in Seattle:
Omelchenko
Beebe
*/
詳細については、「join 句 (C# リファレンス)」および「select 句 (C# リファレンス)」を参照してください。
各ソース要素のサブセットを選択する
ソース シーケンスの各要素のサブセットを選択するには、主に次の 2 つの方法があります。
ソース要素の 1 つのメンバーのみを選択するには、ドット演算を使用します。 次の例で、Customer オブジェクトには、City という名前の文字列を含むいくつかのパブリック プロパティが含まれているとします。 このクエリを実行すると、文字列の出力シーケンスが生成されます。
var query = from cust in Customers select cust.City;
1 つのソース要素からの複数のプロパティを持つ要素を作成するには、名前付きオブジェクトまたは匿名型を指定したオブジェクト初期化子を使用します。 次の例は、匿名型を使用して、各 Customer 要素の 2 つのプロパティをカプセル化する方法を示しています。
var query = from cust in Customer select new {Name = cust.Name, City = cust.City};
詳細については、「オブジェクト初期化子とコレクション初期化子 (C# プログラミング ガイド)」および「匿名型 (C# プログラミング ガイド)」を参照してください。
インメモリ オブジェクトを XML に変換する
LINQ クエリを使用すると、インメモリ データ構造、SQL データベース、ADO.NET データセット、XML ストリーム、および XML ドキュメントの間でデータ変換を簡単に行うことができます。 インメモリ データ構造のオブジェクトを XML 要素に変換する例を次に示します。
class XMLTransform
{
static void Main()
{
// Create the data source by using a collection initializer.
List<Student> students = new List<Student>()
{
new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores = new List<int>{97, 92, 81, 60}},
new Student {First="Claire", Last="O’Donnell", ID=112, Scores = new List<int>{75, 84, 91, 39}},
new Student {First="Sven", Last="Mortensen", ID=113, Scores = new List<int>{88, 94, 65, 91}},
};
// Create the query.
var studentsToXML = new XElement("Root",
from student in students
let x = String.Format("{0},{1},{2},{3}", student.Scores[0],
student.Scores[1], student.Scores[2], student.Scores[3])
select new XElement("student",
new XElement("First", student.First),
new XElement("Last", student.Last),
new XElement("Scores", x)
) // end "student"
); // end "Root"
// Execute the query.
Console.WriteLine(studentsToXML);
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
このコードを実行すると、次の XML 出力が生成されます。
< Root>
<student>
<First>Svetlana</First>
<Last>Omelchenko</Last>
<Scores>97,92,81,60</Scores>
</student>
<student>
<First>Claire</First>
<Last>O'Donnell</Last>
<Scores>75,84,91,39</Scores>
</student>
<student>
<First>Sven</First>
<Last>Mortensen</Last>
<Scores>88,94,65,91</Scores>
</student>
</Root>
詳細については、「C# での XML ツリーの作成 (LINQ to XML)」を参照してください。
ソース要素に対して操作を実行する
出力シーケンスには、ソース シーケンスの要素または要素のプロパティが 1 つも含まれない場合があります。 代わりに、ソース要素を入力引数として使用することで得られた値のシーケンスを出力として生成できます。 次の簡単なクエリを実行すると、double 型の要素のソース シーケンスに基づいて計算された値を表す文字列のシーケンスが出力されます。
注意
クエリが他のドメインに変換される場合、クエリ式でのメソッド呼び出しはサポートされません。 たとえば、LINQ to SQL で C# の通常のメソッドを呼び出すことはできません。これは、C# のメソッドのコンテキストが SQL Server にないためです。 ただし、ストアド プロシージャをメソッドにマップして呼び出すことは可能です。 詳細については、「ストアド プロシージャ (LINQ to SQL)」を参照してください。
class FormatQuery
{
static void Main()
{
// Data source.
double[] radii = { 1, 2, 3 };
// Query.
IEnumerable<string> query =
from rad in radii
select String.Format("Area = {0}", (rad * rad) * 3.14);
// Query execution.
foreach (string s in query)
Console.WriteLine(s);
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Area = 3.14
Area = 12.56
Area = 28.26
*/
参照
処理手順
方法 : LINQ の結合を使用してデータを結合する (Visual Basic)