2010-11-18 6 views
3

Northwindデータベースの2つのテーブル、つまり製品とCAの機能をテストするための2つのテーブルを含むEntity Frameworkモデルを作成しました。このEntity Frameworkクエリから生成されたSQLを理解するのに問題があります

カテゴリと商品の関連付けが自動的に作成されました.0.1〜*です。

私はこの単純なクエリ書いた:私は、SQLプロファイラを実行し、私はそれが生成したSQLを見ることができるようにコードを実行し、これはそれが発生したものです

var beverages = from p in db.Products.Include("Category") 
       where p.Category.CategoryName == "Beverages" 
       select p; 

var beverageList = beverages.ToList(); 

を:

SELECT 
    [Extent1].[ProductID] AS [ProductID], 
    [Extent1].[ProductName] AS [ProductName], 
    [Extent1].[SupplierID] AS [SupplierID], 
    [Extent1].[QuantityPerUnit] AS [QuantityPerUnit], 
    [Extent1].[UnitPrice] AS [UnitPrice], 
    [Extent1].[UnitsInStock] AS [UnitsInStock], 
    [Extent1].[UnitsOnOrder] AS [UnitsOnOrder], 
    [Extent1].[ReorderLevel] AS [ReorderLevel], 
    [Extent1].[Discontinued] AS [Discontinued], 
    [Extent3].[CategoryID] AS [CategoryID], 
    [Extent3].[CategoryName] AS [CategoryName], 
    [Extent3].[Description] AS [Description], 
    [Extent3].[Picture] AS [Picture] 
FROM [dbo].[Products] AS [Extent1] 
    INNER JOIN [dbo].[Categories] AS [Extent2] 
     ON [Extent1].[CategoryID] = [Extent2].CategoryID] 
    LEFT OUTER JOIN [dbo].[Categories] AS [Extent3] 
     ON [Extent1].[CategoryID] = [Extent3].[CategoryID] 
WHERE N'Beverages' = [Extent2].[CategoryName] 

私はなぜクエリの内部がカテゴリに参加してからそれに結合を残したのか不思議です。 selectステートメントは、左の結合テーブルのフィールドを使用しています。誰かが私にこれの理由を理解するのを助けることができますか?左結合を削除し、Extent2からプルする選択リストを変更すると、このクエリで同じ結果が得られます。どのような状況でこれは真実ではないでしょうか?

+1

使用しているEFのバージョンは何ですか? – Sorax

+0

私はEntity Framework 4を使用しています – Dismissile

答えて

2

[Extent3]は「メイン」から選択結果に影響を与えるべきではありませんInclude(Category)の実現であるとインクルードテーブル製品、LEFT JOIN(製品のすべてのレコードと、右側のテーブルカテゴリのレコード)この場合には、それは強い制限(INNER JOIN

なぜ2になるよう

[Extent2]は、名前「飲料」との関連テーブルカテゴリですべてのレコードをフィルタリングすることは本当にありますか? :)式ごとの式と自動生成の構文解析のために(Include、Where)

+1

基本的にクエリジェネレータは、IncludeとWhereが同じテーブルで動作していることを確認するのに十分スマートではありませんか? – Dismissile

+0

多くの場合、@Dismissile:単純です。私は、スマートS​​QL Serverがこれらの小さな問題を解決できることが時々あると思います。楽しいために手書きで作成されたクエリや自動生成されたクエリをテストしてみてください。どのようにしても適合性(EF)は得られますがパフォーマンスは低いです:( – garik

1

あなたは、クエリは、CategoriesテーブルのコピーからSELECTリスト内のすべての列を引っ張っていることに気づくでしょうが​​をエイリアスが、それはExtent2別名コピーに対して区分名をチェックです。

つまり、このシナリオでは、EFのクエリ生成では、Include()であり、同じテーブルを介してクエリを制限していることを認識していないため、2つのコピーを盲目的に使用しています。

残念ながら、何が起こっているかを説明超え、EFとの私の経験は、ソリューションを提案するために十分進んでいない...

0

(質問は同じですが、コメントフィールドがこのためにはあまりにも制限されている場合、

.Include()を省略した場合は、どこからでもロードされません。一般的にはInclude()の代わりに投影を使用するように私には多くの意味があります:

var beverages = from p in db.Products.Include("Category") 
       where p.Category.CategoryName == "Beverages" 
       select new { Product = p, Category = p.Category }; 

var beverageList = beverages.ToList(); 
+1

インクルードを省略した場合、「選択」投影に含めるとカテゴリーのみが読み込まれます。「where」節は自動的にロードされませんカテゴリテーブルのデータ。 – StriplingWarrior

1

djacobsonとイゴールはかなりよくこの問題が発生した理由を説明します。私が個人的にEntity Frameworkを使用する方法では、Includeを完全に使用することは避けます。あなたがデータをどうする計画している内容に応じて、あなたはこのような何かを行うことができ少なくともEF 4.0で、ただ一つの内部生成されます、

var beverages = from p in db.Products 
       select new {p, p.Category} into pc 
       where pc.Category.CategoryName == "Beverages" 
       select pc;      
return beverages.ToList().Select(pc => pc.p); 

は...参加します。 Entity Frameworkは、製品のCategoryプロパティにデータベースから戻ってきたカテゴリが設定されるようにするために十分スマートです。

もちろん、SQL Serverはオブジェクトを最適化して、実際には何も得られない可能性が非常に高いです。

関連する問題