NpGsql EntityFramework 6 - “操作已经在进行中”

Posted

技术标签:

【中文标题】NpGsql EntityFramework 6 - “操作已经在进行中”【英文标题】:NpGsql EntityFramework 6 - "An operation is already in progress" 【发布时间】:2016-04-05 07:06:06 【问题描述】:

我正在开发一个使用 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();

此错误的原因是什么以及如何解决?

【问题讨论】:

旁注:PostGre Sql:哦,嗯???使用Postgres or PostgreSQL 你用的是哪个版本的NpgSql?如果你部署在 mono 上是哪个版本? NpgSql 3.0.4.0,实体框架 6.0 在 Mono 3.x 中发现了类似的问题,但在升级到 4.x 后得到了解决。尝试降级到 NpgSql 2.2.7 看到同样的问题,EF 6.1.3,NpgSql 3.0.5 【参考方案1】:

我已经成功地在 linq 查询之后使用ToList&lt;T&gt; 解决了这个问题,如下所示:

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&lt;T&gt; 可以解决问题。 .Net 将 linq 语句的执行推迟到最后一刻,这可能是问题的一部分。我试图在 foreach 中使用 q 但没有成功。

【讨论】:

【参考方案2】:

问题是由GetUsers() 方法的返回类型引起的。由于是IEnumerable&lt;User&gt;,LINQ-to-SQL 会将结果加载到内存中(逐行),随后的WhereOrderBySelectCount 等调用将在内存中执行。当评估Where 条件时,原始结果集仍在迭代,但关系User.Role 需要在数据库上解决(这就是“操作已在进行中”错误消息的来源)。

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

另请参阅此相关问题/答案:Returning IEnumerable<T> vs. IQueryable<T>

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

【讨论】:

以上是关于NpGsql EntityFramework 6 - “操作已经在进行中”的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 5.0 PostgreSQL (Npgsql) 默认连接工厂

Entity Freamwork 6连接PostgreSql数据库

首先是EF6 postgresql数据库,无法生成模型

npgsql 和 Entity Framework 代码第一次设置问题

将 npgsql 配置为与 .NET 3.5 和 EF 一起使用

不能在 Entity Framework 6.1.3 和 PostgreSQL 中使用打开的事务