为什么使用EF代码的插入首先会在TransactionScope中失败?

本文关键字:TransactionScope 失败 EF 代码 插入 为什么 | 更新日期: 2023-09-27 18:02:18

我有一种情况,我在一个表(asset_type)中创建了一条记录,并通过第二个表(资产)中的外键引用它。在这种情况下,这两个插入都发生在同一个TransactionScope中。

当使用原始DbConnection时,插入成功:

conn.ConnectionString = "host=localhost;port=5432;database=test_client_alpha;user id=tcauser;password=tcapw";    
using (var trans = new TransactionScope())
{
  conn.Open();
  conn.EnlistTransaction(Transaction.Current);
  var cmd = conn.CreateCommand();
  cmd.CommandText = "INSERT INTO overview.asset_type ( name ) VALUES( 'Unknown' ) RETURNING id";
  var assetTypeId = (int)cmd.ExecuteScalar();
  cmd.CommandText = string.Format("INSERT INTO overview.asset "
                                  + "(asset_type_id, client_id, is_active, is_gps_active, is_virtual, default_lon, default_lat) "
                                  + "VALUES ({0}, 'mid', TRUE, TRUE, FALSE, 0, 0 ) "
                                  + "RETURNING id ", assetTypeId);
  var assetId = (int)cmd.ExecuteScalar();
  trans.Complete();
}

然而,如果我切换到使用DbContext类,第二次插入(到资产)失败,违反了外键约束,就像第一次插入(到asset_type)没有发生一样:

conn.ConnectionString = "host=localhost;port=5432;database=test_client_alpha;user id=tcauser;password=tcapw";
using (var trans = new TransactionScope())
{
  using (var context = new TestContext(conn, false))
  {
    var assetTypeId = context.Database
      .SqlQuery<int>("INSERT INTO overview.asset_type ( name ) VALUES( 'Unknown' ) RETURNING id")
      .Single();
    var assetId = context.Database
      .SqlQuery<int>(string.Format("INSERT INTO overview.asset "
                                    + "(asset_type_id, client_id, is_active, is_gps_active, is_virtual, default_lon, default_lat) "
                                    + "VALUES ({0}, 'mid', TRUE, TRUE, FALSE, 0, 0 ) "
                                    + "RETURNING id ", assetTypeId))
      .Single();
    trans.Complete();
  }
}

如果我删除TransactionScope, DbContext示例将正常执行。

我试着玩IsolationLevel设置(ReadCommitted, ReadUncommitted)没有成功。

我意识到在这个例子中不需要TransactionScope。这是一个更大的代码块的一部分,涉及到与多个数据库的交互,并需要一个分布式事务。

我的数据库是PostgreSQL,我正在使用DevArt的dotConnect . net驱动程序。

是否有人有任何洞察为什么DbContext的例子不工作?

为什么使用EF代码的插入首先会在TransactionScope中失败?

管理连接和事务:

实体框架只在需要时打开连接,例如执行查询或调用SaveChanges,然后在操作完成时关闭连接。

  • 调用以下任何方法打开连接:
  • 保存更改或刷新ObjectContext.
  • FirstOrDefault或First on ObjectQuery
  • Load on EntityCollection.
  • 加载实体引用。
  • 任何语言集成查询(LINQ)方法或ObjectQuery查询生成器方法,如Where、OrderBy或Select。

然后打开另一个连接,事务范围抛出异常。你必须设置Distributed Transaction Coordinator(不能说它是真实的或不是PostgreSQL)。

如果它是真实的,那么,在设置DTC之后,只需在作用域中打开您的conn对象。

相关文章:
  • 没有找到相关文章