2009-10-09 8 views
1

J'essaie d'obtenir une requête qui va chercher plusieurs tags. Les tags sont basés sur DB et je les ai liés à l'entité avec une table de jonction. Si je recherche avec 1 tag, j'obtiens les résultats corrects, mais si je recherche avec 2 tags, j'obtiens seulement les entités qui correspondent au second tag.LINQ: multiple Où les appels n'utilisent que le dernier?

est ici le code C# qui construit le IQueryable:

var awTable = db.Artworks.Where(aw => true); //default get all 

    awTable = awTable.Where(aw => (bool)aw.IsArtworkVisible ); 


    foreach (SearchTag tagToMatch in tagList) 
       { 

        awTable = awTable.Where(aw => aw.ArtworkName.Contains(tagToMatch.SearchTagText) 
               || db.SearchTag_x_Artworks.Where(stxa => stxa.SearchTagID == tagToMatch.SearchTagID) 
               .Select(stxa => stxa.ArtworkID).Contains(aw.ArtworkID)); 


       } 

Voici le SQL résultant, qui, si je le brancher dans une fenêtre de requête et définissez les valeurs des paramètres, comprend à la fois où les clauses et renvoie la liste correcte des entités. (WTF!?!?)

{SELECT [t0].[ArtworkID], [t0].[ArtworkName], ... [t0].[MediumID] 
FROM [dbo].[Artworks] AS [t0] 
WHERE ((EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [dbo].[SearchTag_x_Artwork] AS [t1] 
    WHERE ([t1].[ArtworkID] = [t0].[ArtworkID]) AND ([t1].[SearchTagID] = @p0) 
    )) OR ([t0].[ArtworkName] LIKE @p1)) AND ((EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [dbo].[SearchTag_x_Artwork] AS [t2] 
    WHERE ([t2].[ArtworkID] = [t0].[ArtworkID]) AND ([t2].[SearchTagID] = @p2) 
    )) OR ([t0].[ArtworkName] LIKE @p3)) AND (([t0].[IsArtworkVisible]) = 1) 
} 

C'est un peu flippant, tous les conseils sont appréciés. Merci.

+1

Ce qui est vraiment perturbant, c'est pourquoi vous faites certaines choses: 'var awTable = db.Artworks.Where (aw => true); // default get all' ... wat – JustLoren

+0

J'ai essayé d'omettre une instruction if pour plus de clarté: var awTable = db.Artworks.Where (aw => true); si (! EstAuthenticated) { awTable = awTable.Where (aw => (bool) aw.IsArtworkVisible); } –

Répondre

2

Je pense que votre problème a à voir avec les poignées de façon C# les variables capturées dans fermetures comme vos expressions lambda. Vous capturez la même variable tagToMatch. S'il vous plaît essayez ceci:

foreach (SearchTag tagToMatch in tagList) 
    { 
     SearchTag localTagToMatch = tagToMatch; 
     awTable = awTable.Where(aw => aw.ArtworkName.Contains(localTagToMatch .SearchTagText) 
               || db.SearchTag_x_Artworks.Where(stxa => stxa.SearchTagID == localTagToMatch .SearchTagID) 
               .Select(stxa => stxa.ArtworkID).Contains(aw.ArtworkID)); 
    } 

s'il vous plaît lire The Beauty of Closures par Jon Skeet.

+0

Ding ding ding! Holy merde qui fonctionne! Merci! Merci aussi pour le lien, car il n'est pas vraiment évident qu'il se passe quelque chose comme le dernier SearchTag où tous les Where lambdas obtiennent leurs valeurs de paramètres, donc je vais devoir lire à ce sujet. –

1
var awTable = db.Artworks.Where(aw => (bool)aw.IsArtworkVisible); //the first was unnecessary 

foreach (SearchTag tagToMatch in tagList) 
{ 
    awTable = awTable.AndAlso(aw => 
     aw.ArtworkName.Contains(tagToMatch.SearchTagText) || 
     db.SearchTag_x_Artworks.Where(stxa => stxa.SearchTagID == tagToMatch && stxa.ArtworkID == aw.ArtworkID); 
} 
+0

Hmmm, ma version de LINQ n'a pas le AndAlso. Je vais devoir chercher cela et voir si je peux le télécharger. –

Questions connexes