Linq to entities de nombreux de nombreux de sélection: Comment faire pour forcer la génération d'une JOINTURE à la place d'une clause de sous-sélection?
À l'aide de EF DB d'abord j'ai deux entités (Fournisseur, Produit) qui ont un plusieurs-à-plusieurs relations. Entity Framework ne permet pas de créer une entité pour la table associée (SupplierProduct) que les associés de la table contient uniquement la clé primaire de la forte entités.
J'ai eu tous les Fournisseurs qui ne fournissent pas un produit donné avec la requête suivante:
var q1 = context.Suppliers.Where(s=>!s.Products.Any(p=>p.Id == 1));
SQL produit utilise un EXISTE dépendant de la sous-requête similaire à ceci:
SELECT *
FROM Suppliers s
WHERE NOT EXISTS
(SELECT 1
FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)
Est-il possible, à l'aide de Linq to entities méthode de la syntaxe, de produire une requête qui utilise des jointures sur la table associée à la place?
ie:
SELECT DISTINCT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId != 1
Mise à jour
Comme l'a souligné JoeEnos mes questions ci-dessus ne font pas la même chose. La n'EXISTE PAS de sous-requête est probablement la meilleure façon d'aller ici. Que faire si j'essayais d'obtenir tous les fournisseurs qui ne d'approvisionnement d'un produit? Je voudrais changer ma requête linq to entities légèrement à:
var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));
Et le SQL généré serait:
SELECT *
FROM Suppliers s
WHERE EXISTS
(SELECT 1
FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)
Ce qui est bien, j'obtiens le résultat que je souhaite. Cependant, si j'écrivais SQL dans ce cas je le ferais normalement:
SELECT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId = 1
Ma requête linq to entities être modifié pour produire le SQL ci-dessus?
En outre, cet exemple serait beaucoup plus facile à lire avec une meilleure vie réelle de l'échantillon, comme les Voitures<-->Pilotes ou quelque chose comme ça.
très bien, mis à jour avec un exemple réel. Ma requête existante est exactement ce que je veux, cependant, si j'ai été à l'aide de SQL je ne voudrais pas écrire une requête comme ça, je voudrais utiliser une jointure à la place. Je me demande comment je peux le faire avec Linq to entities.
Merci, beaucoup plus facile à lire.
user1914530 j'ai changé la question titre un peu plus précise sur ce que vous semblez vouloir, une jointure au lieu d'une sous-sélection.
OriginalL'auteur | 2013-02-26
Vous devez vous connecter pour publier un commentaire.
Pour générer du SQL où une jointure est utilisé à la place de EXISTE lors de la sélection d'une entité basée sur son m:n association avec une autre entité SelectMany() peut être utilisé. Par exemple:
Peut être réécrite:
Je viens de résoudre, var t1 = contexte.Produits.Où(p => p.Id == 1).SelectMany(p => p.Fournisseurs, (p, a) => new { p,,});
OriginalL'auteur
Vos deux requêtes de faire des choses très différentes. Votre
Any
/EXISTS
requête obtient les fournisseurs qui n'ont pas de produit 1. VotreJOIN
requête obtient tous les fournisseurs qui ont des produits autres que 1, indépendamment de si oui ou non ils ont produit 1.Je ne pense pas que vous pouvez faire ce que vous êtes à la recherche pour, avec juste une
JOIN
etWHERE
- vous pouvez le faire avec unIN
clause, mais je pense que leEXISTS
requête est la plus correcte de la recherche de vos données.Dans tous les cas, l'une des choses merveilleuses au sujet de Entity Framework, c'est que vous n'avez pas à vous soucier de ce qui est généré, à condition que le LINQ déclaration est ok, alors il va trouver la meilleure façon de la rédaction de la requête, et vous ne devriez jamais avoir à le regarder. C'est particulièrement vrai lorsque vous faites de pagination et d'autres choses comme ça, où l'LINQ est simple, mais le SQL généré est horriblement laid.
OriginalL'auteur Joe Enos