LINQ: несколько Где звонки использует только последний? - PullRequest
1 голос
/ 09 октября 2009

Я пытаюсь запустить запрос, который будет искать несколько тегов. Теги основаны на БД, и я связал их с сущностью с помощью соединительной таблицы. Если я ищу по 1 тегу, я получаю правильные результаты, но если я ищу по 2 тегам, я получаю только объекты, которые соответствуют второму тегу.

Вот код C #, который создает 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 ) );


                }

Вот результирующий 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 ]

2 голосов
/ 09 октября 2009

Я думаю, что ваша проблема связана с тем, как C # обрабатывает захваченные переменные в замыканиях , как ваши лямбда-выражения.

Ваш захват одной и той же переменной 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 ) );
  }

Пожалуйста, прочитайте Красота замыканий от Джона Скита.

1 голос
/ 09 октября 2009
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);
}
...