Search code examples
c#.netlinqflickr

Linq: Adding Extra 'Where' Clause Gives Random Results


I'm a beginner in using Linq and a lot of it is completely confusing right now.

I downloaded and used the LinqFlickr library from http://linqflickr.codeplex.com. I think however that this is just my lack of understanding about Linq. There isn't much documentation on the LinqFlickr project for me to go on.

If I run the following code, if the username string is blank, it runs fine and returns photos with a specific tag. But if there is a username in it, it should refine the previous results by specific users, instead it gives me a bunch of random photos.

            var photos = (from ph in context.Photos
                      where
                      ph.SearchMode == SearchMode.TagsOnly
                      && ph.SearchText == tag
                      && ph.PhotoSize == PhotoSize.Small
                      && ph.Extras == (ExtrasOption.Owner_Name |  ExtrasOption.Date_Taken)
                      select ph);

            if (username != "")
            {
                string personId = (from people in context.Peoples
                                where 
                                people.Username == username
                                select people.Id).First();
                photos = photos.Where(q => q.NsId == personId) ;
            }

            photos = photos.Take(10);

I tried using some debugging tools such as LinqPad and MetaLinq but I haven't been able to solve it with them.

Also, I'm sure my Linq query could be made in one query which would be great, but please explain it so a Linq newbie can understand!


Solution

  • Your query looks fine. My guess would be that this is a bug (or unintuitive by-design behaviour) in Athena where an extra "chained" where clause causes the original where clause to be forgotten.

    Assemble the second query independently (i.e. all the constraints in one big where clause) and check that this fixes things. If it does, it's definitely a bug in the API. You can work around this by using LINQKit to assemble and expand the predicate for the where clause dynamically. Here's how this might look:

    // Original predicate without userId constraint
    Expression<Func<Photo, bool>> predicate = ph =>  
            ph.SearchMode == SearchMode.TagsOnly
         && ph.SearchText == tag
         && ph.PhotoSize == PhotoSize.Small
         && ph.Extras == (ExtrasOption.Owner_Name |  ExtrasOption.Date_Taken);
    
    if (!string.IsNullOrEmpty(username)) 
    {
        // Build the userId constraint into the predicate.
    
        var personId = (from people in context.Peoples
                        where  people.Username == username
                        select people.Id).First();
    
        // "And" combines the predicates
        // "Expand" removes the use of invocation expressions, which 
        // some LINQ providers have problems with.
        predicate = predicate.And(q => q.NsId == personId).Expand();
    }
    
    // Final result
    var photos = context.Photos.Where(predicate).Take(10);