代码之家  ›  专栏  ›  技术社区  ›  Rei Miyasaka

实体框架查询中的自定义函数有时转换正确,有时不正确

  •  2
  • Rei Miyasaka  · 技术社区  · 14 年前

    我有这个功能:

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

    它在这个查询中工作得很好:

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

    但它在这个稍微复杂一点的查询中不起作用:

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

    我收到此错误消息:

    NotSupportedException:实体的Linq不识别方法“System.Linq.iQueryable” 1[TheFraser.Data.Articles.Article] WhereArticleIsLive(System.Linq.IQueryable 1[fraser.data.articles.article])方法,此方法无法转换为存储表达式。

    你知道为什么吗?有没有其他方法可以像这样合并查询参数?

    事先谢谢。

    1 回复  |  直到 14 年前
        1
  •  3
  •   jeroenh    14 年前

    编辑:克雷格更正。

    我把这个留在这里,因为我认为它是一个很有价值的工具:使用 linqkit !但不是为了解决这个问题。

    不要返回IQueryable,而是使用表达式来分解谓词。例如,您可以在文章中定义以下静态方法:

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

    然后,确保在构建查询时存储对该表达式的引用,这是沿着(未测试的)行的内容:

    var isLive = Article.IsLive();
    
    from s in Series
    from a in Articles.Where(isLive)
    where s.Id == a.SeriesId
    select new { s, a }