Enumerable.Empty<T>().AsQueryable();此方法支持 LINQ to Entities 基础结构,不打算直接从您的代码中使用

Posted

技术标签:

【中文标题】Enumerable.Empty<T>().AsQueryable();此方法支持 LINQ to Entities 基础结构,不打算直接从您的代码中使用【英文标题】:Enumerable.Empty<T>().AsQueryable(); This method supports the LINQ to Entities infrastructure and is not intended to be used directly from your code 【发布时间】:2016-10-15 09:08:04 【问题描述】:

我收到运行时错误

此方法支持 LINQ to Entities 基础架构,不支持 旨在直接从您的代码中使用。

描述:执行过程中发生了未处理的异常 当前的网络请求。请查看堆栈跟踪以获取更多信息 有关错误的信息以及它在代码中的来源。

异常详细信息:System.InvalidOperationException:此方法 支持 LINQ to Entities 基础结构,并非旨在 直接从您的代码中使用。

我正在尝试生成查询,而不是过滤每个搜索条件,而是通过在所有搜索字段上添加所有匹配记录来包含(将使用OR 而不是AND)。

public static IQueryable<T> ApplySearch<T>(this IQueryable<T> queryable, SearchModel search) where T : class 

    var results = Enumerable.Empty<T>().AsQueryable();
    if (search != null)
    
        if (search.PolicyNumber.HasValue && typeof (IPolicyNumber).IsAssignableFrom(queryable.ElementType))
        
            results = results.Union(queryable.SearchByPolicyNumber(search));
        

        if (search.UniqueId.HasValue && typeof (IUniqueId).IsAssignableFrom(queryable.ElementType))
        
            results = results.Union(queryable.SearchByUniqueId(search));
        

        if (!string.IsNullOrWhiteSpace(search.PostCode) && typeof(IPostCode).IsAssignableFrom(queryable.ElementType))
        
            results = results.Union(queryable.SearchByPostCode(search));
        
    

    return results;

当我介绍 var results = Enumerable.Empty&lt;T&gt;().AsQueryable(); 时,机制开始失效,我需要从空的东西开始。

如何从空集开始,然后在顶部构建 Linq-to-sql 结果?

【问题讨论】:

猜测:queryable.Take(0) 可能会成功。 确切地指出此异常发生的位置可能是个好主意。 @spender 就在 .ToList() 之前 @spender 这个查询将在其他地方实现,即使问题就在这里。它在哪里实现并不重要。他通过确定问题的根源并仅表明这一点,很好地完成了工作。 @spender 在将数据传递给 View 之前被调用的那个,直到那时它都在表达式树中。 【参考方案1】:

您可以通过只合并您拥有的结果来重构代码以不需要空集:

public static IQueryable<T> ApplySearch<T>(this IQueryable<T> queryable, SearchModel search) where T : class 

    var subQueries = new List<IQueryable<T>>();
    if (search != null)
    
        if (search.PolicyNumber.HasValue && typeof (IPolicyNumber).IsAssignableFrom(queryable.ElementType))
        
            subQueries.Add(queryable.SearchByPolicyNumber(search));
        

        if (search.UniqueId.HasValue && typeof (IUniqueId).IsAssignableFrom(queryable.ElementType))
        
            subQueries.Add(queryable.SearchByUniqueId(search));
        

        if (!string.IsNullOrWhiteSpace(search.PostCode) && typeof(IPostCode).IsAssignableFrom(queryable.ElementType))
        
            subQueries.Add(queryable.SearchByPostCode(search));
        
    

    return subQueries.DefaultIfEmpty(queryable)
        .Aggregate((a, b) => a.Union(b));

【讨论】:

嗨服务。当我看到名单被介绍时——我就像“他在想什么!一个名单!”?但后来我意识到你做了什么,我必须说 - 这太棒了...... :) 谢谢。 @IvanStoev 您可以添加DefaultIfEmpty 来定义行为。如果它甚至是受支持的情况,这将取决于规格想要它是什么。我最初的怀疑是它想使用queryable 作为默认值。 @IvanStoev 在我的情况下我返回了return subQueries.Any() ? subQueries.Aggregate((a, b) =&gt; a.Union(b)) : queryable; 我的表中有一个 XML 列,因此由于 Union 试图在幕后“区分”(据我所知),我最终使用了 Concat:'code' if (subQueries.Count > 0) var finalQuery = subQueries.DefaultIfEmpty().Aggregate((resultQuery, addedQuery) => resultQuery.Concat(addedQuery));返回最终查询; else return Enumerable.Empty().AsQueryable(); @AustinRhymer 在这种情况下,问题的要求是专门合并一些在编译时未知的查询。如果您碰巧需要对未知数量的查询执行不同的操作,那么您确实需要相应地更改解决方案。【参考方案2】:

我使用过的临时 hack

是变化自

var results = Enumerable.Empty<T>().AsQueryable();

var results = queryable.Where(o => false);

【讨论】:

但据我了解,更改会很昂贵,因为它会针对每条记录运行。

以上是关于Enumerable.Empty<T>().AsQueryable();此方法支持 LINQ to Entities 基础结构,不打算直接从您的代码中使用的主要内容,如果未能解决你的问题,请参考以下文章

Enumerable.Empty<T> 需要显式转换

Enumerable.Empty<T>().AsQueryable();此方法支持 LINQ to Entities 基础结构,不打算直接从您的代码中使用

Generation 操作

发布后如何填写下拉列表

为啥与空列表连接时返回列表但与新列表连接时不返回?

在 mvc 中加载 2 个下拉列表的更好方法