views:

289

answers:

2

Hi folks,

I've got the following code in my Services project, which is trying to grab a list of posts based on the tag ... just like what we have here at SO (without making this a meta.stackoverflow.com question, with all due respect....)

This service code creates a linq query, passes it to the repository and then returns the result. Nothing too complicated. My LINQ filter method is failing with the following error :-

Method 'Boolean Contains(System.String)' has no supported translation to SQL.

I'm not sure how i should be changing my linq filter method :( Here's the code...

public IPagedList<Post> GetPosts(string tag, int index, int pageSize)
{
    var query = _postRepository.GetPosts()
        .WithMostRecent();

    if (!string.IsNullOrEmpty(tag))
    {
        query = from q in query
                    .WithTag(tag) // <--- HERE'S THE FILTER
                select q;
    }

    return query.ToPagedListOrNull(index, pageSize);
}

and the Filter method...

public static IQueryable<Post> WithTag(this IQueryable<Post> query,
    string tag)
{
    // 'TagList' (property) is an IList<string>
    return from p in query
           where p.TagList.Contains(tag)
           select p;
}

Any ideas? I'm at a loss :(

+1  A: 

Try with Any:

public static IQueryable<Post> WithTag(this IQueryable<Post> query,
    string tag)
{
    // 'TagList' (property) is an IList<string>
    return from p in query
           where p.TagList.Any(t => t == tag)
           select p;
}

.

UPDATE (by PureKrome)

Another suggestion by Ahmad (in a comment below). This uses the Contains method so it will return all posts that contain the tag 'Test', eg. Post with Tag 'Testicle' :-

public static IQueryable<Post> WithTag(this IQueryable<Post> query,
    string tag)
{
    // 'TagList' (property) is an IList<string>
    return from p in query
           where p.TagList.Any(t => t.Contains(tag))
           select p;
}
bruno conde
Genius!!! Could you kindly elaborate more on how an ANY and a CONTAINS might differ theoritically? are they the same (in theory) but just different syntax? Obviously the linq to _SQL_ implimentation are different for either...
Pure.Krome
This happens because the Contains method your using is a member of IList and not a *special* Linq extension method like Any. So, it has no translation associated when the query is being converted to SQL. You can use Contains if you already have the results in memory doing as List<string> like @Ahmad Mageed suggested. Of course, doing the filtering in SQL is better.
bruno conde
Interestingly, both the ANY and the List+Contains does an exact string match. So if i search for the tag 'Test' it only returns all posts which contain at least one tag that is exactly 'Test'. If a tag has 'Testicles' then it's not returned.
Pure.Krome
@Pure.Krome: if you want that to work you could modify bruno's code and use the string contains method on t: Any(t => t.Contains(tag))
Ahmad Mageed
Awesome Ahmad! Awesome :)
Pure.Krome
A: 

In WithTag try changing the query to use a List rather than an IList:

return from p in query
       let taglist = p.TagList as List<string>
       where taglist.Contains(tag)
       select p;

Also check out this answer, which is similar to my suggestion: Stack overflow in LINQ to SQL and the Contains keyword

Ahmad Mageed
For completion it is also possible to use the Any method the same way with the above code to achieve partial matches if desired: taglist.Any(t => t.Contains(tag))
Ahmad Mageed