views:

31

answers:

1

I have this function:

public static IQueryable<Article> WhereArticleIsLive(this IQueryable<Article> q)
{
    return q.Where(x =>
        x != null
        && DateTime.UtcNow >= x.PublishTime
        && x.IsPublished
        && !x.IsDeleted);
}

And it works just fine in this query:

from a in Articles.WhereArticleIsLive()
where a.Id == 5
select new { a.Title }

But it doesn't work in this only slightly more complex query:

from s in Series
from a in Articles.WhereArticleIsLive()
where s.Id == a.SeriesId
select new { s, a }

I get this error message:

NotSupportedException: LINQ to Entities does not recognize the method 'System.Linq.IQueryable1[TheFraser.Data.Articles.Article] WhereArticleIsLive(System.Linq.IQueryable1[TheFraser.Data.Articles.Article])' method, and this method cannot be translated into a store expression.

Any idea why? Is there another way to consolidate query parameters like this?

Thanks in advance.

+2  A: 

EDIT: corrections by Craig.

I'm leaving this here, because I think it's a valuable tool: Use linqkit! But not for solving this question though :-)

Instead of returning IQueryable, use Expression to factor out predicates. E.g. you could define the following static method on Article:

public static Expression<Func<Article,bool>> IsLive()
{
    return x =>
    x != null
    && DateTime.UtcNow >= x.PublishTime
    && x.IsPublished
    && !x.IsDeleted
}

Then, ensure to store a reference to this expression when building your query, something along the lines of (not tested):

var isLive = Article.IsLive();

from s in Series
from a in Articles.Where(isLive)
where s.Id == a.SeriesId
select new { s, a }
jeroenh
This is almost right. (1) `Expression` is the right way to go. (2) You don't need LINQKit (which is great for other stuff) for this task, nor `Compile`, etc. (3) The key is to store a reference to the expression, i.e.: `Expression<Func<Article,bool>> isLive = Article.IsLive(); from s in Series from a in Articles.Where(isLive)`
Craig Stuntz
@Craig Stuntz: thanks for the feedback, I updated my answer accordingly
jeroenh
Ahhhh, so that's what Expression is for.Thanks for linqkit too, I'm sure it'll come in handy.
Rei Miyasaka