2012-04-04 2 views
1

Je viens d'un terrain TSQL + C# et j'ai essayé de m'adapter à linq et EF. Les relations de plusieurs à plusieurs m'ont fait trébucher. J'ai des modèles avec plusieurs-à-plusieurs relations que je veux interroger à partir d'une base de données. Tels que:Entity Framework: Obtenir un modèle avec des modèles liés dans plusieurs à plusieurs relations

 class Product{ 
     public int ID {get;set;} 
     public string ProductName {get;set;} 
     public virtual ICollection<Tag> Tags {get;set;} 
    } 

    class Tag { 
     public int ID {get;set;} 
     public string TagName {get;set;} 
     public virtual ICollection<Product> Products {get;set;} 

    } 

Je suis en mesure d'obtenir un produit lui-même de la DbContext, puis aller chercher plus tard, il est Tags associés comme ceci:

// product exists in memory as a Product with an empty product.Tags 

var query = from p in db.Product 
      from t in db.Tags 
      where p.ID == product.ID 
      select p.Tags; 

Ensuite, je peux attribuer les product.Tags avec les étiquettes récupérées. Évidemment, c'est très inefficace quand il s'agit de plusieurs produits si je dois interroger chaque produit. Avec linq et EF, je veux être en mesure d'obtenir un produit avec tous ses tags associés dans un aller-retour à la base de données. En outre, je veux pouvoir obtenir tous les produits et leurs étiquettes associées (ou une liste filtrée de produits). Comment le linq ressemblerait-il?

Edit:

Ok, après un peu plus bidouiller, j'ai ceci:

var query = db.Product.Include("Tags") 
      .Where(p => p.Tags.Any(t => t.Products.Select(m => m.ID).Contains(p.ID))); 

C'est presque ce que je dois. Les résultats sont tous des produits avec des étiquettes. Manquant sont les produits qui n'ont pas de balises. Je pense à cela comme l'équivalent d'une jointure interne SQL. Je veux laisser l'extérieur joindre les étiquettes au produit, et renvoyer tous les produits avec des étiquettes facultatives. Comment obtenir tous les produits avec leurs tags associés sans exclure les produits sans tags?

Éditer:

C'était plus facile que je ne le pensais.

var query2 = db.Product.Include("Tags").DefaultIfEmpty(); 

Ceci permet d'obtenir tous les produits et leurs étiquettes respectives, y compris les produits sans étiquettes. Espérons que cela fonctionne pour les bonnes raisons ...

Répondre

0

Le but de l'utilisation d'un mappeur relationnel d'objet comme EF est que mappe les relations pour vous. Si vous joignez manuellement des objets contenant des clés étrangères dans la base de données, vous vous trompez.

Voir ma question Why use LINQ Join on a simple one-many relationship?

La bonne réponse est tout simplement context.Products.Include("Tags"), qui rejoindront automatiquement par magie les produits et les étiquettes pour vous. C'est littéralement le plus grand (seulement?) Avantage d'utiliser un ORM.

Questions connexes