NpGsql EntityFramework 6 - "An operation is already in progress" NpGsql EntityFramework 6-“操作已经在进行中”

10

我正在使用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();
}

这个错误的原因是什么,如何解决?


1
附注:PostGre Sql :O,嗯???请使用Postgres或PostgreSQL - Vivek S.
你使用的是哪个版本的NpgSql?如果你在mono上部署,它是哪个版本? - Orif Khodjaev
NpgSql 3.0.4.0,Entity Framework 6.0 - teenup
在Mono 3.x中发现了类似的问题,但在升级到4.x后得到了解决。尝试降级到NpgSql 2.2.7。 - Orif Khodjaev
看到相同的问题,EF 6.1.3,NpgSql 3.0.5。 - neo112
在 https://github.com/npgsql/npgsql/issues/826 上存在一个未解决的缺陷。我们在 Mono 4.2.2 上看到了这个问题。 - Matt Z
2个回答

8

在 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,但没有成功。

4
问题的原因在于`GetUsers()`方法的返回类型。它是`IEnumerable`,因此LINQ-to-SQL将结果加载到内存中(逐行加载),随后的`Where`、`OrderBy`、`Select`、`Count`等调用将在内存中执行。当评估`Where`条件时,原始结果集仍然在迭代,但关系`User.Role`需要在数据库上解析(这就是"An operation is already in progress"错误消息来自的地方)。
如果将返回类型更改为`IQueryable`,则查询将在调用`Count`方法之前不会执行,并且整个查询都将转换为SQL,只返回计数,而不会将任何`User`记录加载到内存中。
另请参阅相关问题/答案:Returning IEnumerable<T> vs. IQueryable<T> 建议调用查询的`ToList()`方法将整个结果集加载到内存中,这可以解决您的错误,但根据结果集的大小,可能效率非常低下。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接