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

Posted

技术标签:

【中文标题】不能在 Entity Framework 6.1.3 和 PostgreSQL 中使用打开的事务【英文标题】:Cant use opened transaction in Entitiframework 6.1.3 with PostgreSQL 【发布时间】:2017-10-21 08:02:45 【问题描述】:

我一直在尝试将 EntityFramework6.Npgsql 与事务一起使用,但是当我调用 DbContext.UseTransaction 方法时出现上述异常。

错误信息(最新的 InnerException):

“Npgsql.PostgresException (0x80004005): 25P02: 当前事务被中止,命令被忽略直到事务块结束”

所以,我创建了一个新项目来模拟并尝试找出导致问题的原因。

测试代码

try

    using (var conn = new Npgsql.NpgsqlConnection(ConfigurationManager.AppSettings["app:pgconn"]))
    
        conn.Open();
        using (var transaction = conn.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted))
        
            using (var ctx = new CadastrosContext(conn))
            
                var tenant = new Tenant();
                ctx.Database.UseTransaction(transaction);
                ctx.Tenants.Add(tenant);
                await ctx.SaveChangesAsync()
                    .ConfigureAwait(false);
                Debug.WriteLine($"Tenant 1 Id: tenant.TenantId");
            
            using (var ctx = new CadastrosContext(conn))
            
                var tenant = new Tenant();
                ctx.Database.UseTransaction(transaction);
                ctx.Tenants.Add(tenant);
                await ctx.SaveChangesAsync()
                    .ConfigureAwait(false);
                Debug.WriteLine($"Tenant 2 Id: tenant.TenantId");
            
            await transaction.CommitAsync();
        
    

catch (Exception ex)

    throw;
  

包 id="EntityFramework" 版本="6.1.3" targetFramework="net462" 包 id="EntityFramework6.Npgsql" 版本="3.1.1" targetFramework="net462" 包 id="Npgsql" 版本="3.1.2" targetFramework="net462"

最奇怪的行为是当我第二次调用该动作时它起作用了! 经过数小时调查问题的根源(使用其他数据库代码按预期工作)后,我发现当我切换到 EF6 的第一个版本时,它可以正常工作。

有效的软件包

包 id="EntityFramework" 版本="6.1.0" targetFramework="net462" 包 id="EntityFramework6.Npgsql" 版本="3.1.1" targetFramework="net462" 包 id="Npgsql" 版本="3.1.2" targetFramework="net462"

大家也有这个问题吗?? 出现Npgsql/EntityFramework6.Npgsql不支持新版EntityFramework的bug?

【问题讨论】:

【参考方案1】:

我今天遇到了同样的问题,我唯一能找到的就是你的问题。 :)

对数据库的第一次查询总是失败并出现错误:当前事务被中止,直到事务块结束的命令被忽略。

就我而言,PostgreSQL 日志如下所示:

2019-07-15 14: 43: 40.260 +07 [12364] ERROR: the relation "dbo.EdmMetadata" does not exist (symbol 51)
2019-07-15 14: 43: 40.260 +07 [12364] OPERATOR: SELECT "Extent1". "Id", "Extent1". "ModelHash" FROM "dbo". "EdmMetadata" AS "Extent1" ORDER BY "Extent1" . "Id" DESC LIMIT 1
2019-07-15 14: 43: 40.649 +07 [12364] ERROR: the current transaction is aborted, the commands until the end of the transaction block are ignored
2019-07-15 14: 43: 40.649 +07 [12364] OPERATOR: DELETE FROM "MS". "MessageReference" WHERE E'T '= "Mark"

在执行我的查询之前,EF 尝试从不存在的表dbo.EdmMetadata 中获取数据,查询失败并且未提交事务。需要此查询来将用于创建数据库的模型的哈希值与您当前的模型进行比较。但是,如果您在现有数据库中使用 Code First,则该表不存在。

为避免此错误,您可以通过将 null 设置为数据库初始化器来禁用模型哈希检查

static YourContext()

   System.Data.Entity.Database.SetInitializer<BaseDynamicDbContext>(null);

在我的例子中,我需要初始化器在应用程序启动时迁移到最新版本,所以我创建了空的 dbo.EdmMetadata 表,以防止第一次查询错误。

create table "dbo"."EdmMetadata"
(
  "Id"        integer not null
    constraint "PK_EdmMetadata"
    primary key,
  "ModelHash" varchar(50)
);

【讨论】:

教程:entityframeworktutorial.net/code-first/…

以上是关于不能在 Entity Framework 6.1.3 和 PostgreSQL 中使用打开的事务的主要内容,如果未能解决你的问题,请参考以下文章

如何将针对 Entity Framework .Net 4.6.1 的库与 .Net Core 应用程序一起使用

Entity Framework 学习日记

为啥我的 Entity Framework Code First 代理集合为空,为啥我不能设置它?

entity framework 性能真那么差

如何使用 Entity Framework Code First V6.1.2 进行集成测试

Entity Framework Core 迁移命令