如何连接 IQueryable<T> 和 List<T>

Posted

技术标签:

【中文标题】如何连接 IQueryable<T> 和 List<T>【英文标题】:How to concat IQuerable<T> and List<T> 【发布时间】:2019-11-21 20:02:09 【问题描述】:

我有 BaseDocumentTextDocumentExcelDocumentWordDocument 课程。他们继承自BaseDocument。我有每个类的集合。假设BaseDocuments 集合从某些地方的某些子实体集合中获取价值。集合类型不同,其中一些是 List,另一种是 IQuerable 和另一种特定类型。 BaseDocuments 集合是 IQuerable 类型并从某些子实体集合中获取值。它看起来像这样:

 using (Context context = new Context())
 
    var words = context.GetEntities<BaseDocument>().Where(e => e.Name.StartsWith("Word")).ToList(); // type of collection is list

    var excels = context.GetEntities<BaseDocument>().Where(e => e.Name.StartsWith("Excel"));

    var texts = context.GetEntities<BaseDocument>().Where(e => e.Name.StartsWith("Text"));

    var wordsAsQuery = words.AsQueryable();

    baseDocuments = wordsAsQuery.Concat(excels).Concat(texts);
 

如您所见,我正在使用 Concat 方法。但是当我做var instaces = baseDocuments.ToList(); 时,它会抛出异常:

System.InvalidOperationException: '此方法支持 LINQ 实体基础设施,不打算直接从 你的代码。'

我做了一些研究,每次修复代码后,我都会遇到另一个异常,例如

LINQ 错误 DbUnionAllExpression 需要兼容的参数 集合 ResultTypes。

我可以对所有子集合进行 ToList,但这没有意义,而且会出现性能问题。

如何将不同类型的集合连接到 IQuerable 集合?可能吗?

更多关于model的信息可以看我最后一个问题:Loading instance of entity takes more than 1 second

【问题讨论】:

为什么不直接打电话给context.BaseDocuments.Where( condition || condition || condition).ToList() AsQueryable很少有用。删除它。 @TheGeneral,因为 condition1,condition2 ... 用在不同的地方,在子集合中,我们不知道。我们知道只有子集合和基础集合从中获得价值 如果您能提供minimal reproducible example 这样我们就可以重现该问题,那就太好了。 minimal reproducible example 必须包含所需的一切(包括GetEntities)。 @KanisXXX 您的解释确实具有误导性。使用 LINQ to Objects 时,您可以轻松地将List(一个类)与任何IEnumerable(一个接口)连接起来。与问题无关。 【参考方案1】:

为什么您首先ToListing Word 文档,然后对它们执行AsQueryable?您正在导致 LINQ 忘记有关数据库结构的所有内容并处理内存中的 word 集合。然后,当您使用实际查询将其告知Concat 时,您会得到您指定的错误。为什么不只是:

using (Context context = new Context())

   var words = context.GetEntities<BaseDocument>().Where(e => e.Name.StartsWith("Word"));

   var excels = context.GetEntities<BaseDocument>().Where(e => e.Name.StartsWith("Excel"));

   var texts = context.GetEntities<BaseDocument>().Where(e => e.Name.StartsWith("Text"));

   baseDocuments = words.Concat(excels).Concat(texts);

【讨论】:

我这样做是因为单词集合的类型是列表。我也对此发表评论 @DIlshod words 集合的类型是List,因为您很乐意调用ToList。正如我所展示的,这样做没有意义,您的代码示例可以很容易地修复。我不明白你的评论。 试想一下,这句话是 List 集合而不是 IQuerable

以上是关于如何连接 IQueryable<T> 和 List<T>的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 IQueryable<T>.Element 类型是不是为接口

如何分配 IQueryable<T> 的属性值?

如何将 IEnumerable<t> 或 IQueryable<t> 转换为 EntitySet<t>?

如何将 ODataQueryOptions<T> 应用于 IQueryable<X>

如何将 Kendo UI Grid 与 ToDataSourceResult()、IQueryable<T>、ViewModel 和 AutoMapper 一起使用?

在 WebAPI 中使用 OData 时如何将 SelectExpandQueryOption 转换为 IQueryable<T>?