所以我有一些代码可以通过Oracle ODP.NET更新一组数据库表。更新需要是原子的,因此需要在事务中运行。但是代码可以在两个不同的场景中调用:一个已经启动了一个事务(我需要共享),一个不会(因此我需要自己开始)。
我的问题是,我认为没有简单的方法可以检查Oracle连接是否已启动事务。可能的解决方案(我都不满意):
尝试创建新事务并捕获异常(如果已经启动)
Try
tx = OracleConnection.BeginTransaction
Catch ex As Exception
'do something
End Try
问题:使用异常进行正常程序流控制的不良做法
问题:Oracle用户需要访问系统表。
m_oraTransaction
,我可以通过反射检索。 问题:因为某种原因而私有。
有更好的方法吗?
NB。我在Oracle12c中看到Oracle连接上有一个LogicalTransactionId
属性。我认为这可能表明Oracle发现了一个缺陷并添加了这个属性。
答案 0 :(得分:1)
当DML语句至少更新一行时,Oracle会物理创建事务(以及V $ TRANSACTION中的记录)。
使用V $ TRANSACTION并不理想,因为您需要额外的权限才能访问此视图。
我知道的最简单的检查是SELECT DBMS_TRANSACTION.LOCAL_TRANSACTION_ID FROM DUAL
。如果它返回NOT NULL值,则表示已创建物理事务(或者您已经在之前启动的现有事务中)。
我在OracleConnection.LogicalTransactionId
中从未见过任何其他值而非null。
答案 1 :(得分:0)
使用System.Transactions.TransactionScope?
public void Senario1()
{
using (var transaction = new TransactionScope())
{
//your odp.net op here:
//var cmd = new OracleCommand();
//also do senario2 - the outer TransactionScope here will be detected by the new one in senario2
Senario2();
transaction.Complete();
}
}
public void Senario2()
{
using (var transaction = new TransactionScope())
{
//your odp.net op here:
//var cmd = new OracleCommand();
transaction.Complete();
}
}