使用AsEnumerable

时间:2017-10-30 13:26:50

标签: linq entity-framework-6 datareader

我使用以下函数使用我以编程方式构建的一堆查询表达式来查询EF6模型:

    /// <summary>
    /// Common application of generated queries to select the required resources
    /// </summary>
    /// <typeparam name="T">The EF model type</typeparam>
    /// <param name="source">The source of models (a DbSet)</param>
    /// <param name="queries">A collection of query pairs (database, local) to be applied as Where clauses</param>
    /// <returns></returns>
    protected static IEnumerable<string> ApplyCriteriaBase<T>(IQueryable<T> source, IEnumerable<(Expression, Expression)> queries) where T : DbResource
    {
        // Apply the database queries sequentially as Where clauses
        var resources = queries
            .Select(p => p.Item1)
            .Aggregate(source, (ds, qry) => ds.Where(qry as Expression<Func<T, bool>>))
            .Distinct();

        // If there are no local queries then don't bother fetching the whole object, just select the id in the generated SQL
        if(queries.All(q => q.Item2 == null))
            return resources
                .Select(a => a.Id.ToString());

        // Apply local queries
        // AsEnumerable() escapes from the IQueryable monad so the subsequent queries are executed locally on IEnumerable
        // This requires fetching the whole object because we dont know which bit is to be tested by the local query
        // Note that IEnumerable doesn't understand query expressions so we have to compile them to code and then invoke them
        return queries
            .Select(p => p.Item2)
            .Where(q => q != null)
            .Aggregate(
                resources.ToList() as IEnumerable<T>,  // .AsEnumerable() doesn't work
                (ds, qry) => ds.Where((qry as Expression<Func<T, bool>>).Compile().Invoke))
            .Select(a => a.Id.ToString());
    }

这个想法是查询包含2元组的查询表达式,其中每个查询表达式中的第一个将针对数据库(MySql)运行,而第二个(如果存在)将针对返回的EF模型运行。 据我所知,AsEnumerable()应允许第二个查询在本地和懒惰地执行而不将所有结果都拉入内存。不幸的是,这失败了错误:

  

“已经有一个与此Connection关联的开放DataReader   必须先关闭。“

示例中显示的修复,将结果流转换为List,正常工作但严格。 为什么AsEnumerable()不起作用,是否存在另一种懒惰处理结果的方法? DbResource的一些实例非常大,我只想累积每个资源的Id。

谢谢, 安迪

0 个答案:

没有答案