NpGsql EntityFramework 6 - "An operation is already in progress"



我正在进行一个项目,使用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将结果加载到内存中(逐行),随后的WhereOrderBySelectCount等调用将在内存中执行。当评估Where条件时,原始结果集仍在迭代,但关系User.Role需要在DB上解析(这就是"操作已在进行中"错误消息的来源)。

如果返回类型更改为IQueryable<User>,则在调用Count方法之前不会执行查询,此外,整个查询将被转换为SQL,只返回计数,而不会将任何User记录加载到内存中。

另请参阅此相关问题/答案:返回IEnumerable<T>相对于IQueryable<T>

建议对查询调用ToList()的答案会将整个结果集加载到内存中,这会使错误消失,但根据结果集的大小,效率也可能非常低。

相关内容

最新更新