Visual Studio 2010 EF4 POCO Part2

前回はEF4で追加される予定のPOCOを解説しました。V1ではエンティティをデータ層として利用すべきか、ドメイン層で利用すべきか、という白熱した??議論がありました。EF4ではPOCOが導入されることで非常にスマートなアプリケーションアーキテクチャの構築が期待できます。

では、今日は実際にVisual Studio 2010 Beta1日本語版を用いてシンプルな実装方法を見ていきましょう(尚、あくまでデモ用でありベストプラクティスではないので予めご了承ください)。サンプルデータベースにはNorthwindを利用します。

Step1 – モデルの作成と、コード生成機能の解除

EF4でPOCO実装を行う場合、以前と同様にEDMが必要になります。このため、3.5 SP1での実装方法と同様にデザイナやその他の手段でCSDL、SSDL、MSLを作成する必要があります。ここでは、ADO.NET Entity Data Model ウィザードを用いてedmxファイルを生成します。

1. コンソールアプリケーションのプロジェクトを生成します。名前はNorthwindPocoPJとします。

2. POCOを定義するためのクラスライブラリのプロジェクトを追加します。名前をNorthwindModelとします。

3. NorthwindPocoPJプロジェクトでNorthwindModelプロジェクトへの依存関係を追加します。また「参照の追加」でNorthwindModelプロジェクトを追加しておきます。

4. NorthwindPocoPJプロジェクト上で、[追加]→[新しい項目]からNorthwind.edmxという名前でADO.NET Entity Data Modelを生成します。ここではEDMにCategoriesとProductsを追加します。また、「生成されたオブジェクトの名前を複数化または単数化する」にチェックしておきましょう。(以前の記事、Pluralizationで説明しました。)

これでEDMの生成が完了しました。

以降、コーディングを行うことになりますが、今回はエンティティやコンテキストは自前で用意します。そのためコードジェネレーション機能はオフにしておきましょう。Northwind.edmxのプロパティから「カスタムツール」に設定されている「EntityModelCodeGenerator」を削除します。これでモデルのためのコードジェネレーション機能がOFFになります。この操作でNorthwind.edmxのコードビハインドがプロジェクトに存在しないことが確認できると思います。

以上でPOCOエンティティを作成する準備ができました。

Step2 – POCOエンティティの作成

今回はCategoryとProductエンティティを作成してみましょう。これらをNorthwindModelプロジェクトに追加します。

まずは、Categoryエンティティのためのサンプルコードです。

public class Category

{

public int CategoryID { get; set; }

public string CategoryName { get; set; }

public string Description { get; set; }

public byte[] Picture { get; set; }

public virtual List<Product> Products { get; set; }

}

モデルの中のナビゲーションプロパティはList<Product>として変換されています。また、遅延ロードを有効にするためにvirtualキーワードを指定しています。

同様にProductエンティティを下記のようにコーディングします。

     public class Product    {        public int ProductID { get; set; }        public string ProductName { get; set; }        public int SupplierID { get; set; }        public string QuantityPerUnit { get; set; }        public decimal UnitPrice { get; set; }        public Int16 UnitsInStock { get; set; }        public Int16 UnitsOnOrder { get; set; }        public Int16 ReorderLevel { get; set; }        public bool Discontinued { get; set; }        public Category Category { get; set; }    }

これでPOCOの実装は完了です。

Step3 – Contextの作成

では次にObjectContextを実装します。このObjectContextがアプリケーションとEntity Frameworkの接着剤のような役割を果たします。このObjectContextはNorthwindPocoPJプロジェクトに作成します。

public class NorthwindContext : ObjectContext

{

public NorthwindContext() : base("name=NorthwindEntities", "NorthwindEntities")

{

_categories = CreateObjectSet<Category>();

_products = CreateObjectSet<Product>();

}

public ObjectSet<Category> Categories

{

get

{

return _categories;

}

}

private ObjectSet<Category> _categories;

public ObjectSet<Product> Products

{

get

{

return _products;

}

}

private ObjectSet<Product> _products;

}

Step4 – クエリ

下記のようにクエリすることが可能です。

NorthwindContext db = new NorthwindContext();

var beverages = from p in db.Products

where p.Category.CategoryName == "Beverages"

select p;

きちんとリレーションシップナビゲーションも機能しておりProductエンティティから関連するCategoryエンティティを取得できているのが確認できます。

また、下記のようにDeferredLoadingEnabledを指定することで遅延ロードにも対応していることが確認できます。ただし、前述したようにリレーションシップにvirtualキーワードを指定する必要があるので注意してください。

NorthwindContext db = new NorthwindContext();

db.ContextOptions.DeferredLoadingEnabled = true;

var cats = from c in db.Categories

select c;

foreach (var c in cat)

{

Console.WriteLine(c.CategoryName);

foreach (var p in c.Products)

{

Console.WriteLine(" " + p.ProductName);

}

}

以上で、簡単ですがPOCOの具体的な実装をご覧いただきました。次回ももう少しPOCOの解説をしたいと思います。

関連リソース(英語です)

ADO.NET team blog

Persistence Ignorant (MSDN)