简体   繁体   English

IEnumerable 和 IQueryable 可以联合吗?

[英]Can IEnumerable and IQueryable be Union?

I tried to Union IQueryable and IEnumerable but got this error我尝试联合 IQueryable 和 IEnumerable 但收到此错误

Union(__p_2)' could not be translated. Union(__p_2)' 无法翻译。 Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。

and tried many different writing methods but it doesn't work.并尝试了许多不同的写作方法,但它不起作用。 So can IEnumerable and IQueryable be Union?那么 IEnumerable 和 IQueryable 可以联合吗?

My data looks like the following:我的数据如下所示:

var users = new List<Person>().AsQueryable();
var user = GetUsersByXXX(XXX, YYY);   // return IQueryable<Person>
var userExtra = GetUsersExtraByXXX(XXX, YYY); // return IEnumerable<Person>

if (userExtra.Any())
{
  users = user.Union(userExtra);
}    

return await users.AsNoTracking().OrderBy(x => x.NAME ).ToListAsync();         

class班级

public class Person
{
    public string CODE { get; set; }
    public string NAME { get; set; }
    public string PHONE { get; set; }
}

You must understand those two things are two different concepts:您必须了解这两件事是两个不同的概念:

  • An IQueryable is an interface that "Provides functionality to evaluate queries against a specific data source" IQueryable是一个接口, “提供针对特定数据源评估查询的功能”
  • An IEnumerable is an interface that "Exposes the enumerator, which supports a simple iteration over a collection" . IEnumerable是一个“公开枚举器,支持对集合进行简单迭代”的接口。

An IQueryable can be turned into IEnumerable by calling AsEnumerable() .通过调用AsEnumerable()可以将IQueryable转换为IEnumerable

Note, that an IQueryable can be a non-evaluated expression.请注意, IQueryable可以是非计算表达式。 Ie the data has not been retrieved from the database.即尚未从数据库中检索数据。 By calling something like ToList or AsEnumerable , you enumerate, thus evaluate it.通过调用ToListAsEnumerable之类的东西,您可以枚举,从而评估它。 The normal (synrchonous) methods will block until that's finished.正常(同步)方法将阻塞,直到完成。 That's why there are also ToListAsync and AsAsyncEnumerable .这就是为什么还有ToListAsyncAsAsyncEnumerable的原因。

The IQueryable<T> interface already implements IEnumerable<T> , you just need to cast to IEnumerable<T> to ensure you use the linq-to-objects implementation. IQueryable<T>接口已经实现了IEnumerable<T> ,您只需转换为IEnumerable<T>以确保您使用 linq-to-objects 实现。

var users = GetUsersByXXX(XXX, YYY).AsEnumerable() // "cast" it
    .Union(GetUsersExtraByXXX(XXX, YYY));

The added check to see if the "extra" users is empty is unnecessary.添加检查以查看“额外”用户是否为空是不必要的。 If it's already empty, the union would essentially be a noop.如果它已经是空的,则联合本质上将是一个 noop。

The error message is caused by an error where the query you're generating cannot be translated into SQL.错误消息是由您生成的查询无法转换为 SQL 的错误引起的。 It would appear that IQueryable<T>.Union() cannot be translated to SQL and the error is thrown.似乎IQueryable<T>.Union()无法转换为 SQL 并引发错误。

You would need to work around this by either calling one of the methods mentioned in the error to force the union to be performed in .NET by having Entity Framework retrieve the full set of data for GetUsersByXXX() first and then performs the union in memory.您需要通过调用错误中提到的方法之一来解决此问题,以强制在 .NET 中执行联合,方法是让实体框架首先检索GetUsersByXXX()的完整数据集,然后在内存中执行联合.

var users = new List<T>().AsQueryable();
var user = GetUsersByXXX(XXX, YYY);   // return IQueryable<T>
var userExtra = GetUsersExtraByXXX(XXX, YYY); // return IEnumerable<T>

if (userExtra.Any())
{
  users = user.AsEnumerable().Union(userExtra);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM