今回は ‘Linq to XML’ を使ってデータをXML から取り出したあと、前回と同じクエリを投げてみます。
最初に、少しだけ Prep Work。ここから、Product.xmlをダウンロードして保存してください。保存したパスはあとで使いますので、覚えておいてください – ここでは”C:\data\Product.xml”とします。
次に、Default.aspx.csファイルの中のGetProductList() メソッドを以下のコードに置き換えてください。もともとのGetProductList()はList<Product>をメソッドの中で初期化していました。今回は、同一のデータをproduct.xmlの中から ‘Linq to XML’を使って取り出してきています。
List<Product> GetProductList()
{
var query =
from e in XElement.Load(@"C:\Data\product.xml").Elements("Product")
select new Product()
{
ProductID = (int)e.Element("ProductID"),
CategoryID = (int)e.Element("CategoryID"),
ProductName = (string)e.Element("ProductName"),
UnitPrice = (decimal)e.Element("UnitPrice")
};
return query.ToList();
}
ここでもLINQ のクエリがでてきます。同じことをC# 2.0 で書くと
List<Product> query = new List<Product>();
foreach (XElement e in XElement.Load(@"C:\Data\product.xml").Elements("Product"))
{
Product p = new Product();
p.ProductID = (int)e.Element("ProductID");
p.CategoryID = (int)e.Element("CategoryID");
p.ProductName = (string)e.Element("ProductName");
p.UnitPrice = (decimal)e.Element("UnitPrice");
query.Add(p);
}
になります。このようにシンプルなLINQ クエリはforeachを使って簡単に置き換えられますし、どちらがシンプルかと言うと難しいところですが、何度も書いたImperative -> Declarative (手続き型 -> 論理型) の違いに気づいていただければと思います。
ここで、まだ紹介していなかったC# 3.0 の構文のひとつ、匿名型 - Anonymous Type の説明をします。 Part IVで、’ さきほど追加したグループのコンテナクラスは不要です’ と書いた時点で説明はぶきましたが、匿名型を使うことにより、コンパイラが自動的に型の定義をしてくれます。シンタックスとしては
C# 3.0 – 匿名型Anonymous Type
var anonymousType = new {
Hoge = 1,
Foo = "Anonymous Type"
};
C# 2.0 –型指定した例
var concreteType = new ConcreteType()
{
Hoge = 1,
Foo = "Anonymous Type"
};
…
…
class ConcreteType
{
public int Hoge;
public string Foo;
}
匿名型を使うことにより、C# 2.0 の例にあるようなConcreteTypeをコンパイラがアセンブリの中に定義します。Deep Diveはしませんが、LINQ のクエリの中で匿名型も通常の型もselectできると覚えておいてください。
クエリ内で匿名型を使った例
var result = from p in products
group p by p.CategoryID into g
orderby g.Count() descending
select new //匿名型
{
CategoryID = g.Key,
Count = g.Count()
};
クエリ内で型を指定した例
var query =
from e in XElement.Load(@"C:\Data\product.xml").Elements("Product")
select new Product() // Product型の指定
{
ProductID = (int)e.Element("ProductID"),
CategoryID = (int)e.Element("CategoryID"),
ProductName = (string)e.Element("ProductName"),
UnitPrice = (decimal)e.Element("UnitPrice")
};