2015年09月28日

EntityFramework(6):リレーションシップ その1

   このエントリーをはてなブックマークに追加 Clip to Evernote
NorthwindデータベースのCategoryテーブルとProductsテーブルは、1対多の関係があります。
この場合のデータ参照について見てみます。

Category.csを見てみると、Categoryクラスには、

  public virtual ICollection Products { get; set; }

というプロパティが存在します。 一方、Productクラスには、

  public virtual Category Category { get; set; }

というプロパティが存在します。
ここから、 「一つの製品カテゴリーには、複数の製品が関連付けされている」 「一つの製品には、一つのカテゴリが関連付けされている」 ということがわかります。
このプロパティを使うと、joinする代わりに以下のように書けます。 

 using (var db = new NorthwindContext()) {
     db.SetLogging();
     var query = db.Products
                   .Where(x => x.Category.CategoryName == "Condiments")
                   .Select(x => new {
                      x.ProductID,
                      x.ProductName,
                      x.Category.CategoryName
                   });
     foreach (var p in query) {
         Console.WriteLine($"{p.ProductID} | {p.ProductName} | {p.CategoryName}");
     }
 }

※ SetLogging メソッドは、第3回目の記事で書いたメソッド。
※ Console.WriteLIneのところで、C#6.0の機能を使ってます。

これは、CategoryNameが"Condiments"であるProductを取得しているのですが、 CategoryNameは、ProductsテーブルではなくCategoryテーブルにあるカラムであることに 注目です。
関連するテーブルをC#で慣れ親しんだプロパティを通じてアクセスできるわけです。
実際発行されるSQLは、

SELECT 
    [Extent1].[ProductID] AS [ProductID], 
    [Extent1].[ProductName] AS [ProductName], 
    [Extent2].[CategoryName] AS [CategoryName]
    FROM  [dbo].[Products] AS [Extent1]
    INNER JOIN [dbo].[Categories] AS [Extent2] ON [Extent1].[CategoryID] = [Extent2].[CategoryID]
    WHERE N'Condiments' = [Extent2].[CategoryName]

と join していることが確認できます。
もし、Customerプロパティを使わないとすると、joinを使って、

 using (var db = new NorthwindContext()) {
     db.SetLogging();
     var query = from p in db.Products
                 join c in db.Categories on 
                           p.CategoryID equals c.CategoryID
                 where c.CategoryName == "Condiments"
                 select new {
                     p.ProductID,
                     p.ProductName,
                     c.CategoryName
                 };
     foreach (var p in query) {
         Console.WriteLine($"{p.ProductID} | {p.ProductName} | {p.CategoryName}");
     }
 }

と、より複雑なクエリ式を書く必要があります。
発行される SQLは、以下のように先ほどと同じものになっています。

SELECT 
    [Extent1].[ProductID] AS [ProductID], 
    [Extent1].[ProductName] AS [ProductName], 
    [Extent2].[CategoryName] AS [CategoryName]
    FROM  [dbo].[Products] AS [Extent1]
    INNER JOIN [dbo].[Categories] AS [Extent2] ON [Extent1].[CategoryID] = [Extent2].[CategoryID]
    WHERE N'Condiments' = [Extent2].[CategoryName]




この記事へのコメント
ブログアンテナ登録のご連絡 お世話になります。貴サイト拝見しまして、同様のテーマを集めたニュースサイトを運営配信しております。非常に良いコンテンツを配信されており勝手ながらアンテナに追加させていただきました。(以下URLのヘッダはスパム対策で外しています)quiccastarter245.kiramori.net/an/anprogram/ 相互リンクぜひご検討いただければ幸いです。管理人
Posted by 管理人 at 2015年10月04日 13:46
 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52436995