我有一种情况,我在一个表(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示例不起作用?
答案 0 :(得分:0)
Managing Connections and Transactions:
实体框架仅在需要时打开连接,例如执行查询或调用SaveChanges,然后在操作完成时关闭连接。
然后它打开另一个连接,事务范围抛出异常。你必须设置Distributed Transaction Coordinator
(不能说是PostgreSQL的真实与否)。
如果是真的,那么,在设置完DTC之后,只需打开范围内的conn
对象。