LINQ:多个Where调用只使用最后一个?

时间:2009-10-09 13:58:12

标签: c# linq where

我正在尝试查询将搜索多个标签。标签是基于数据库的,我已经将它们与具有联结表的实体相关联。如果我使用1个标签进行搜索,则会得到正确的结果,但如果我使用2个标签进行搜索,则只能获得与第二个标签匹配的实体。

以下是构建IQueryable的C#代码:

  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 ) );


                }

这是生成的SQL,如果我将其插入查询窗口并设置参数值,则包括where子句并返回正确的实体列表。 (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)
}

这有点令人沮丧,任何建议都表示赞赏。感谢。

2 个答案:

答案 0 :(得分:2)

我认为你的问题与C#处理闭包中捕获变量的方式有关,就像你的lambda表达式一样。

您捕获相同的变量tagToMatch。请试试这个:

  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 ) );
  }

请阅读Jon Skeet撰写的The Beauty of Closures

答案 1 :(得分: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);
}