2010-05-04 6 views
266

Je rencontre des problèmes avec une requête écrite en Linq et Lambda. Jusqu'à présent, je reçois beaucoup d'erreurs, voici mon code:Joints C#/Où avec Linq et Lambda

int id = 1; 
var query = database.Posts.Join(database.Post_Metas, 
           post => database.Posts.Where(x => x.ID == id), 
           meta => database.Post_Metas.Where(x => x.Post_ID == id), 
           (post, meta) => new { Post = post, Meta = meta }); 

Je suis nouveau à l'aide de Linq, donc je ne sais pas si cette requête est correcte.

+6

ce que vous essayez d'accomplir? – GerManson

+2

Que voulez-vous que la requête fasse dans une phrase? – hunter

+4

Vos sélecteurs de clé sont * way * trop compliqués. Si vous voulez sélectionner par ID, juste x => x.ID est bien. –

Répondre

616

Je trouve que si vous êtes familier avec la syntaxe SQL, en utilisant la syntaxe de requête LINQ est beaucoup plus claire, plus naturel, et facilite le repérage des erreurs:

var id = 1; 
var query = 
    from post in database.Posts 
    join meta in database.Post_Metas on post.ID equals meta.Post_ID 
    where post.ID == id 
    select new { Post = post, Meta = meta }; 

Si vous êtes vraiment coincé sur en utilisant lambdas cependant, votre syntaxe est assez éloignée. Voici la même requête, en utilisant les méthodes d'extension LINQ:

var id = 1; 
var query = database.Posts // your starting point - table in the "from" statement 
    .Join(database.Post_Metas, // the source table of the inner join 
     post => post.ID,  // Select the primary key (the first part of the "on" clause in an sql "join" statement) 
     meta => meta.Post_ID, // Select the foreign key (the second part of the "on" clause) 
     (post, meta) => new { Post = post, Meta = meta }) // selection 
    .Where(postAndMeta => postAndMeta.Post.ID == id); // where statement 
+4

@Emanuele Greco, en ce qui concerne votre modification, "Les champs d'égalité sur ID sont définis dans la condition JOIN, vous n'avez pas besoin d'utiliser la clause WHERE!": La clause WHERE ne teste pas l'égalité entre les champs ID. Colonne ID et le paramètre id déclaré en dehors de la requête. –

+2

Super morceau de 'lambda' et citation facile à utiliser et à comprendre – ppumkin

+0

Merci, linq requête claire. –

24

Vos sélecteurs de clé sont incorrects. Ils devraient prendre un objet du type de la table en question et retourner la clé à utiliser dans la jointure. Je pense que vous voulez dire ceci:

var query = database.Posts.Join(database.Post_Metas, 
           post => post.ID, 
           meta => meta.Post_ID, 
           (post, meta) => new { Post = post, Meta = meta }); 

Vous pouvez appliquer la clause where par la suite, et non dans le cadre du sélecteur de clé.

48

Vous pourriez faire deux façons avec ceci. L'utilisation LINQPad (valeur inestimable si vous êtes nouveau à LINQ) et une base de données factice, j'ai construit les requêtes suivantes:

Posts.Join(
    Post_metas, 
    post => post.Post_id, 
    meta => meta.Post_id, 
    (post, meta) => new { Post = post, Meta = meta } 
) 

ou

from p in Posts 
join pm in Post_metas on p.Post_id equals pm.Post_id 
select new { Post = p, Meta = pm } 

Dans ce cas particulier, je pense que la syntaxe LINQ est plus propre (Je change entre les deux en fonction de ce qui est le plus facile à lire). La chose que je tiens à souligner cependant est que si vous avez des clés étrangères appropriées dans votre base de données, (entre post et post_meta) alors vous n'avez probablement pas besoin d'une jointure explicite sauf si vous essayez de charger un grand nombre d'enregistrements. Votre exemple semble indiquer que vous essayez de charger un seul article et que ce sont des métadonnées. Si l'on suppose qu'il ya beaucoup de dossiers post_meta pour chaque poste, alors vous pouvez faire ce qui suit:

var post = Posts.Single(p => p.ID == 1); 
var metas = post.Post_metas.ToList(); 

Si vous voulez éviter le problème n + 1, alors vous pouvez explicitement dire LINQ to SQL pour charger tous les associés éléments en une seule fois (bien que ce soit un sujet avancé lorsque vous êtes plus familier avec L2S). L'exemple ci-dessous dit: « Quand vous chargez un Post, charge également tous ses enregistrements associés via la clé étrangère représentée par la propriété 'Post_metas de »:

var dataLoadOptions = new DataLoadOptions(); 
dataLoadOptions.LoadWith<Post>(p => p.Post_metas); 

var dataContext = new MyDataContext(); 
dataContext.LoadOptions = dataLoadOptions; 

var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically 

Il est possible de faire beaucoup LoadWith appels sur un ensemble unique de DataLoadOptions pour le même type, ou de nombreux types différents. Si vous faites cela bien, vous voudrez peut-être envisager de mettre en cache.

+0

*** LinqPad *** et ** CRM 2016 **? – Kiquenet

2

Il pourrait être quelque chose comme

var myvar = from a in context.MyEntity 
      join b in context.MyEntity2 on a.key equals b.key 
      select new { prop1 = a.prop1, prop2= b.prop1}; 
5

affichage parce que quand j'ai commencé LINQ + EntityFramework, je fixais ces exemples pour une journée.

Si vous utilisez EntityFramework et que vous disposez d'une propriété de navigation nommée Meta sur votre objet de modèle Post, il s'agit d'une solution simple.Si vous utilisez entity et n'avez pas cette propriété de navigation, qu'attendez-vous?

database 
    .Posts 
    .Where(post => post.ID == id) 
    .Select(post => new { post, post.Meta }); 

Si vous le code de faire d'abord, vous souhaitez mettre en place la propriété ainsi:

class Post { 
    [Key] 
    public int ID {get; set} 
    public int MetaID { get; set; } 
    public virtual Meta Meta {get; set;} 
} 
8

Daniel a une bonne explication des relations de syntaxe, mais je mettre ce document ainsi que pour mon équipe afin de le rendre un peu plus simple pour eux de comprendre. Espérons que cela aide quelqu'un enter image description here

1

Cette requête linq devrait fonctionner pour vous. Il obtiendra tout le post qui a post meta.

var query = database.Posts.Join(database.Post_Metas, 
           post => post.postId, // Primary Key 
           meta => meat.postId), // Foreign Key 
           (post, meta) => new { Post = post, Meta = meta }); 

équivalent SQL Query

Select * FROM Posts P 
INNER JOIN Post_Metas pm ON pm.postId=p.postId 
1

Je l'ai fait quelque chose comme ceci;

var certificationClass = _db.INDIVIDUALLICENSEs 
    .Join(_db.INDLICENSECLAsses, 
     IL => IL.LICENSE_CLASS, 
     ILC => ILC.NAME, 
     (IL, ILC) => new { INDIVIDUALLICENSE = IL, INDLICENSECLAsse = ILC }) 
    .Where(o => 
     o.INDIVIDUALLICENSE.GLOBALENTITYID == "ABC" && 
     o.INDIVIDUALLICENSE.LICENSE_TYPE == "ABC") 
    .Select(t => new 
     { 
      value = t.PSP_INDLICENSECLAsse.ID, 
      name = t.PSP_INDIVIDUALLICENSE.LICENSE_CLASS,     
     }) 
    .OrderBy(x => x.name); 
0

1 est égal à 1 deux autre table se joindre

 var query = 
      from post in database.Posts 
      join meta in database.Post_Metas on 1 equals 1 
      where post.ID == id 
      select new { Post = post, Meta = meta }; 
Questions connexes