2015年10月04日

EntityFramework(7):リレーションシップその2

  
いくつかリレーションシップを使った例を紹介しましょう。
ここでは、以下のテーブルを使います。
  1. Category 
  2. Product 
  3. Order 
  4. Order_Detail 

最初の例です。

  using (var db = new NorthwindContext()) {
      var query = (from product in db.Products
                   where product.UnitPrice <= 10
                   from detail in product.Order_Details
                   where detail.Discount > 0
                   select new { 
                       product.ProductID, 
                       product.ProductName, 
                       product.UnitPrice 
                   }).Distinct();
      foreach (var p in query)
          Console.WriteLine($"{p.ProductID} | {p.ProductName} | {p.UnitPrice}");
  }

この例は、UnitPrice が 10 以下の製品で、割り引き有りで売られたことのある 製品を抜き出す例です。

次の例は、Condimentsカテゴリに属する製品のうち、200個以上売上げのあった製 品を抜き出しています。

 using (var db = new NorthwindContext()) {
     var query = db.Products
                   .Where(p => p.Category.CategoryName == "Condiments" &&
                               p.Order_Details.Sum(d => d.Quantity) >= 200);
     foreach (var p in query) {
         Console.WriteLine("{0}  {1}",
                    p.ProductID, p.ProductName);
     }
 }



次に、OrderテーブルとOrder_Detailsの関連に注目し、4つのテーブルを参照する クエリを書いてみます。

 using (var db = new NorthwindContext()) {
     var query = db.Products
                   .Where(x => x.Category.CategoryName == "Condiments");
     var query2 = query.Where(x => x.Order_Details
                                    .Any(o => o.Order.OrderDate < new DateTime(1996, 9, 1)));
     foreach (var p in query2) {
         Console.WriteLine($"{p.ProductID} | {p.ProductName} | {p.CategoryID}");
     }
 }

これは、CategoryNameが"Condiments"である商品のうち、1996/9/1より前に売上げがあった 製品を抜き出している例です。
4つのテーブルを参照するコードも、それほど苦労なく書くことができます。
このように書けるというのは、SQL文が苦手な僕には、夢のようです。

発行されているSQL文を見てみると、Anyメソッドは、SQLのEXIST関数に置き換え られているのが分かります。

SELECT 
    [Extent1].[ProductID] AS [ProductID], 
    [Extent1].[ProductName] AS [ProductName], 
    [Extent1].[SupplierID] AS [SupplierID], 
    [Extent1].[CategoryID] AS [CategoryID], 
    [Extent1].[QuantityPerUnit] AS [QuantityPerUnit], 
    [Extent1].[UnitPrice] AS [UnitPrice], 
    [Extent1].[UnitsInStock] AS [UnitsInStock], 
    [Extent1].[UnitsOnOrder] AS [UnitsOnOrder], 
    [Extent1].[ReorderLevel] AS [ReorderLevel], 
    [Extent1].[Discontinued] AS [Discontinued]
    FROM  [dbo].[Products] AS [Extent1]
    INNER JOIN [dbo].[Categories] AS [Extent2] ON [Extent1].[CategoryID] = [Extent2].[CategoryID]
    WHERE (N'Condiments' = [Extent2].[CategoryName]) AND ( EXISTS (SELECT 
        1 AS [C1]
        FROM  [dbo].[Order Details] AS [Extent3]
        INNER JOIN [dbo].[Orders] AS [Extent4] ON [Extent3].[OrderID] = [Extent4].[OrderID]
        WHERE ([Extent1].[ProductID] = [Extent3].[ProductID]) AND 
              ([Extent4].[OrderDate] < convert(datetime2, '1996-09-01 00:00:00.0000000', 121))
    ))


 

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

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