4

ここに画像の説明を入力してください

最初にEFDBを使用すると、多対多の関係を持つ2つのエンティティ(Supplier、Product)があります。Entity Frameworkは、関連付けられたテーブル(SupplierProduct)のエンティティを作成しません。これは、関連付けられたテーブルに強力なエンティティの主キーのみが含まれているためです。

特定の製品を提供していないすべてのサプライヤーに次のクエリを取得しています。

var q1 = context.Suppliers.Where(s=>!s.Products.Any(p=>p.Id == 1));

生成されたSQLは、次のようなEXISTS依存サブクエリを使用します。

SELECT *
FROM Suppliers s
WHERE NOT EXISTS
  (SELECT 1 
   FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)

Linq to Entitiesメソッド構文を使用して、代わりに関連するテーブルで結合を使用するクエリを生成することは可能ですか?

すなわち:

SELECT DISTINCT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId != 1

アップデート

JoeEnosが指摘しているように、上記の私のクエリは同じことをしません。NOT EXISTSサブクエリは、おそらくここに行くための最良の方法です。製品を供給したすべてのサプライヤーを獲得しようとした場合はどうなりますか?linqをエンティティクエリに少し変更して次のようにします。

var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));

そして、生成されるSQLは次のようになります。

SELECT *
FROM Suppliers s
WHERE EXISTS
  (SELECT 1 
   FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)

どちらでも構いませんが、希望する結果が得られます。ただし、この場合にSQLを記述している場合は、通常、次のようにします。

SELECT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId = 1

linq to entityクエリを変更して、上記のSQLを生成できますか?

4

2 に答える 2

12

別のエンティティとのm:nの関連付けに基づいてエンティティを選択するときに、EXISTSの代わりに結合が使用されるSQLを生成するには、SelectMany()を使用できます。例えば:

var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));

次のように書き換えることができます。

var q1 = context.Products.Where(p => p.Id == 1).SelectMany(p => p.Suppliers);
于 2013-02-26T10:09:03.247 に答える
0

2つのクエリは非常に異なることを行います。Any/クエリEXISTSは、製品1をまったく持っていないサプライヤを取得します。クエリJOINは、製品1を持っているかどうかに関係なく、1以外の製品を持っているすべてのサプライヤを取得します。

探していることをaJOINとだけで実行できるとは思いません。句を使用して実行できますが、WHEREクエリがデータを検索する最も正しい方法だと思います。INEXISTS

いずれにせよ、Entity Frameworkのすばらしい点の1つは、何が生成されるかを心配する必要がないことです。LINQステートメントに問題がない限り、クエリを作成するための最良の方法が見つかります。それを見る必要はありません。これは、ページングなどを行う場合に特に当てはまります。LINQは単純ですが、生成されたSQLはひどく醜いです。

于 2013-02-26T06:31:38.907 に答える