我正在进行一个项目,使用NpGsql EntityFramework 6连接到PostgreSQL数据库。当我尝试在GetAdminUsersCount
:中执行查询时,我得到了问题标题中的异常
public class GenieRepository : IDisposable
{
GenieDbContext db = new GenieDbContext();
public IEnumerable<User> GetUsers()
{
return db.Users;
}
}
public int GetAdminUsersCount()
{
return repo.GetUsers().Where(u => u.Role.RoleName == "Administrator").Count();
}
出现此错误的原因是什么?如何解决?
在LINQ查询之后立即使用ToList<T>
,如下所示:
using (ElisContext db = new ElisContext()) {
var q = from a in db.aktie select a;
List<aktie> akties = q.ToList<aktie>();
foreach (aktie a in akties) {
Console.WriteLine("aktie: id {0}, name {1}, market name {2}"
, a.id, a.name, a.marked.name);
}
}
注意q.ToList<T>
的作用。NET将linq语句的执行延迟到最晚的时刻,这可能是问题的一部分。我曾尝试在foreach
中使用q
,但没有成功。
问题是由GetUsers()
方法的返回类型引起的。由于是IEnumerable<User>
,LINQ to SQL将结果加载到内存中(逐行),随后的Where
、OrderBy
、Select
、Count
等调用将在内存中执行。当评估Where
条件时,原始结果集仍在迭代,但关系User.Role
需要在DB上解析(这就是"操作已在进行中"错误消息的来源)。
如果返回类型更改为IQueryable<User>
,则在调用Count
方法之前不会执行查询,此外,整个查询将被转换为SQL,只返回计数,而不会将任何User
记录加载到内存中。
另请参阅此相关问题/答案:返回IEnumerable<T>相对于IQueryable<T>
建议对查询调用ToList()
的答案会将整个结果集加载到内存中,这会使错误消失,但根据结果集的大小,效率也可能非常低。