【发布时间】:2023-03-21 07:30:02
【问题描述】:
我有一种情况,我在一个表 (asset_type) 中创建一条记录,并通过第二个表 (asset) 中的外键引用它。在这种情况下,这两个插入都发生在同一个 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 类,则第二次插入(到资产中)会失败并违反外键约束,就好像第一次插入(到资产类型中)没有发生一样:
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 示例不起作用吗?
【问题讨论】:
-
我从来没有真正使用过 DbContext 的原始 SQL 方法,但
SqlQuery不是仅用于 READ 操作(查询),ExecuteSqlCommand用于 DML,如 INSERT、UPDATE、DELETE?但是我很惊讶你没有得到例外。 -
我用 SQL Server 和 SQLClient 作为提供者测试了类似的代码(但相同的逻辑:在 table1 中插入 row1,然后在 table2 中插入 row2,FK 到 row1)。它在有和没有
TransactionScope的情况下都有效。问题可能与 PostgreSQL 或 dotConnect 驱动程序有关。
标签: c# .net postgresql transactions entity-framework-4.1