事务回滚不了

AssetSystem 2009-01-04 09:13:53
请教一个问题:您是否遇到过程序开始了事务,而后分别插入记录到几个表,最后由于不符合业务逻辑程序回滚事务,但发现回滚不起作用的问题,记录插入的还是插入了!
数据库: oracle 10g
连接数据: System.Data.OracleClient
事务隔离LEVEl: readcomitted
特别奇怪发现在程序begintran并插入几条记录到几个表后,在用其他工具查看那几个表可以看见记录已经提交了,凭我经验在事务未提交之前除当前程序外其他例程是无法看见那刚插入的记录的!
特别奇怪,用同样的代码于C/S程序事务没有问题,到了WEB就不行了!
...全文
591 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
AssetSystem 2009-01-06
  • 打赏
  • 举报
回复
看来这个问题应该比较难搞,都无人问津了!
skeljy 2009-01-06
  • 打赏
  • 举报
回复
mark
AssetSystem 2009-01-06
  • 打赏
  • 举报
回复
看来这个问题应该比较难搞,都无人问津了!
AssetSystem 2009-01-05
  • 打赏
  • 举报
回复
怎么没人回答
zhaoguoqingluntan 2009-01-05
  • 打赏
  • 举报
回复
先跟下调试下,
是不是你的事务设置有问题.
AssetSystem 2009-01-05
  • 打赏
  • 举报
回复
还是少了些空格,看这份吧,呵呵!

这是我们程序的大概逻辑,我整理下仅列出核心部分的!
可以看见我确实开始了事务,且必要时进行了回滚,但是就是不行,而且仅是本人的电脑不可以!!!

//Web页面:调用中间层
protected void btnSend_Click(objectsender,EventArgse)
{
IInvoker invoker=new Invoker(Session);
stringresult=invoker.Approve(this.caseName,this.tradeNo,string.Empty,-1,MgtAction.Send);//里面如何调用下面中间层代码忽略
}

//中间层:业务对象定位、业务方法执行。可以看见如果需要事务都会开始事务,在异常后会回滚,绝对不会漏掉!
private void Invoke(KeyValuePair<BusinessSeed,BusinessType> business,string action)
{
//从缓冲区获取会话对应的业务对象
object target=business.Key.ManagementObj;

//业务方法字典
IDictionary<string,BusinessMethod>businessMethodDict=business.Value.BusinessMethodsCache;

//获取业务方法事务要求
IsolationLevel isolationLevel=businessMethodDict[action].TransactionAttribute.IsolationLevel;
_TransactionModetransactionMode=businessMethodDict[action].TransactionAttribute.TransactionMode;

//执行业务方法
try
{
//如果需要事务则开始事务
if (transactionMode == _TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_BeginTransation].MethodInfo.Invoke(target,newobject[]{isolationLevel});
}

//执行业务方法
businessMethodDict[action].MethodInfo.Invoke(target,null);//调用下面业务对象的业务方法

//提交事务
if(transactionMode==_TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_CommitTransation].MethodInfo.Invoke(target,null);
}
}
catch(Exceptionexception)
{
//回滚事务
if(transactionMode==_TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_RollbackTransation].MethodInfo.Invoke(target,null);
}

//释放业务对象资源
businessMethodDict[Nut_Constant.BusinessProcedure_Dispose].MethodInfo.Invoke(target,null);

//抛出异常
throw new IoCException(ExceptionMessage.SystemProcessFail+":"+target.GetType().ToString()+","+action,exception);
}

//释放业务对象资源
businessMethodDict[Nut_Constant.BusinessProcedure_Dispose].MethodInfo.Invoke(target,null);
}

//业务层:这里是一个业务类的一个业务方法,其实是一个工作流审批的例子。
[BusinessActionAttribute("Approve")]
[Transaction(_TransactionMode.Required)]//标明是否需要事务控制
public void ApproveManagement()
{
//如下是工作流执行的大概逻辑,当在我机器上调试时,在1处插入记录后2处抛出异常后回滚不了!
//工作流
ISyfWorkFlow workFlow=newSyfWorkFlow<M,D>(businessObj,tradeCode,tradeNo);

//1:如果未为当前单据建立审批流程则创建,否则调入审批流程【此处可能会插入n条记录到n个表】
if(!workFlow.HasInstance())workFlow.CreateInstance() else workFlow.LoadInstance();

//2:执行审批【如果这里业务逻辑验证失败就会发送事务回滚】
workFlow.Perform(SyfBehavior.Approve,comment,false);

//通知后续审批人
workFlow.Inform(SyfBehavior.Approve,SyfInformKind..JobAndMail);

//成功返回
this.Mission.SetActionState(ActionState.OK);
this.Mission.ClearMessageList();
}

//DAO层:由业务层调用,其实是调用Nhibernate的ISession创建一个事务对象,然后开始或回滚事务的。
public virtual voidBeginTransation(IsolationLevelisolationLevel)
{
if(isolationLevel==IsolationLevel.Unspecified)isolationLevel=IsolationLevel.ReadCommitted;
this._iTransaction=this.CreateISession().BeginTransaction(isolationLevel);
}

//DAO层:事务回滚
public virtual void RollbackTransation()
{
this._iTransaction.Rollback();
}
AssetSystem 2009-01-05
  • 打赏
  • 举报
回复
少了些空格,看这个份吧!

这是我们程序的大概逻辑,我整理下仅列出核心部分的!
可以看见我确实开始了事务,且必要时进行了回滚,但是就是不行,而且仅是本人的电脑不可以!!!

//Web页面:调用中间层
protected void btnSend_Click(objectsender,EventArgse)
{
IInvokerinvoker=newInvoker(Session);
stringresult=invoker.Approve(this.caseName,this.tradeNo,string.Empty,-1,MgtAction.Send);//里面如何调用下面中间层代码忽略
}

//中间层:业务对象定位、业务方法执行。可以看见如果需要事务都会开始事务,在异常后会回滚,绝对不会漏掉!
private void Invoke(KeyValuePair<BusinessSeed,BusinessType>business,stringaction)
{
//从缓冲区获取会话对应的业务对象
objecttarget=business.Key.ManagementObj;

//业务方法字典
IDictionary<string,BusinessMethod>businessMethodDict=business.Value.BusinessMethodsCache;

//获取业务方法事务要求
IsolationLevelisolationLevel=businessMethodDict[action].TransactionAttribute.IsolationLevel;
_TransactionModetransactionMode=businessMethodDict[action].TransactionAttribute.TransactionMode;

//执行业务方法
try
{
//如果需要事务则开始事务
if (transactionMode == _TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_BeginTransation].MethodInfo.Invoke(target,newobject[]{isolationLevel});
}

//执行业务方法
businessMethodDict[action].MethodInfo.Invoke(target,null);//调用下面业务对象的业务方法

//提交事务
if(transactionMode==_TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_CommitTransation].MethodInfo.Invoke(target,null);
}
}
catch(Exceptionexception)
{
//回滚事务
if(transactionMode==_TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_RollbackTransation].MethodInfo.Invoke(target,null);
}

//释放业务对象资源
businessMethodDict[Nut_Constant.BusinessProcedure_Dispose].MethodInfo.Invoke(target,null);

//抛出异常
thrownewIoCException(ExceptionMessage.SystemProcessFail+":"+target.GetType().ToString()+","+action,exception);
}

//释放业务对象资源
businessMethodDict[Nut_Constant.BusinessProcedure_Dispose].MethodInfo.Invoke(target,null);
}

//业务层:这里是一个业务类的一个业务方法,其实是一个工作流审批的例子。
[BusinessActionAttribute("Approve")]
[Transaction(_TransactionMode.Required)]//标明是否需要事务控制
public void ApproveManagement()
{
//如下是工作流执行的大概逻辑,当在我机器上调试时,在1处插入记录后2处抛出异常后回滚不了!
//工作流
ISyfWorkFlow workFlow=newSyfWorkFlow<M,D>(businessObj,tradeCode,tradeNo);

//1:如果未为当前单据建立审批流程则创建,否则调入审批流程【此处可能会插入n条记录到n个表】
if(!workFlow.HasInstance())workFlow.CreateInstance() else workFlow.LoadInstance();

//2:执行审批【如果这里业务逻辑验证失败就会发送事务回滚】
workFlow.Perform(SyfBehavior.Approve,comment,false);

//通知后续审批人
workFlow.Inform(SyfBehavior.Approve,SyfInformKind..JobAndMail);

//成功返回
this.Mission.SetActionState(ActionState.OK);
this.Mission.ClearMessageList();
}

//DAO层:由业务层调用,其实是调用Nhibernate的ISession创建一个事务对象,然后开始或回滚事务的。
public virtual voidBeginTransation(IsolationLevelisolationLevel)
{
if(isolationLevel==IsolationLevel.Unspecified)isolationLevel=IsolationLevel.ReadCommitted;
this._iTransaction=this.CreateISession().BeginTransaction(isolationLevel);
}

//DAO层:事务回滚
public virtual void RollbackTransation()
{
this._iTransaction.Rollback();
}
AssetSystem 2009-01-05
  • 打赏
  • 举报
回复
这是我们程序的大概逻辑,我整理下仅列出核心部分的!
可以看见我确实开始了事务,且必要时进行了回滚,但是就是不行,而且仅是本人的电脑不可以!!!

//Web页面:调用中间层
protectedvoidbtnSend_Click(objectsender,EventArgse)
{
IInvokerinvoker=newInvoker(Session);
stringresult=invoker.Approve(this.caseName,this.tradeNo,string.Empty,-1,MgtAction.Send);//里面如何调用下面中间层代码忽略
}

//中间层:业务对象定位、业务方法执行。可以看见如果需要事务都会开始事务,在异常后会回滚,绝对不会漏掉!
privatevoidInvoke(KeyValuePair<BusinessSeed,BusinessType>business,stringaction)
{
//从缓冲区获取会话对应的业务对象
objecttarget=business.Key.ManagementObj;

//业务方法字典
IDictionary<string,BusinessMethod>businessMethodDict=business.Value.BusinessMethodsCache;

//获取业务方法事务要求
IsolationLevelisolationLevel=businessMethodDict[action].TransactionAttribute.IsolationLevel;
_TransactionModetransactionMode=businessMethodDict[action].TransactionAttribute.TransactionMode;

//执行业务方法
try
{
//如果需要事务则开始事务
if (transactionMode == _TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_BeginTransation].MethodInfo.Invoke(target,newobject[]{isolationLevel});
}

//执行业务方法
businessMethodDict[action].MethodInfo.Invoke(target,null);//调用下面业务对象的业务方法

//提交事务
if(transactionMode==_TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_CommitTransation].MethodInfo.Invoke(target,null);
}
}
catch(Exceptionexception)
{
//回滚事务
if(transactionMode==_TransactionMode.Required)
{
businessMethodDict[Nut_Constant.BusinessProcedure_RollbackTransation].MethodInfo.Invoke(target,null);
}

//释放业务对象资源
businessMethodDict[Nut_Constant.BusinessProcedure_Dispose].MethodInfo.Invoke(target,null);

//抛出异常
thrownewIoCException(ExceptionMessage.SystemProcessFail+":"+target.GetType().ToString()+","+action,exception);
}

//释放业务对象资源
businessMethodDict[Nut_Constant.BusinessProcedure_Dispose].MethodInfo.Invoke(target,null);
}

//业务层:这里是一个业务类的一个业务方法,其实是一个工作流审批的例子。
[BusinessActionAttribute("Approve")]
[Transaction(_TransactionMode.Required)]//标明是否需要事务控制
publicvoidApproveManagement()
{
//如下是工作流执行的大概逻辑,当在我机器上调试时,在1处插入记录后2处抛出异常后回滚不了!

//工作流
ISyfWorkFlowworkFlow=newSyfWorkFlow<M,D>(businessObj,tradeCode,tradeNo);

//1:如果未为当前单据建立审批流程则创建,否则调入审批流程【此处可能会插入n条记录到n个表】
if(!workFlow.HasInstance())workFlow.CreateInstance()elseworkFlow.LoadInstance();

//2:执行审批【如果这里业务逻辑验证失败就会发送事务回滚】
workFlow.Perform(SyfBehavior.Approve,comment,false);

//通知后续审批人
workFlow.Inform(SyfBehavior.Approve,SyfInformKind..JobAndMail);

//成功返回
this.Mission.SetActionState(ActionState.OK);
this.Mission.ClearMessageList();
}

//DAO层:由业务层调用,其实是调用Nhibernate的ISession创建一个事务对象,然后开始或回滚事务的。
publicvirtualvoidBeginTransation(IsolationLevelisolationLevel)
{
if(isolationLevel==IsolationLevel.Unspecified)isolationLevel=IsolationLevel.ReadCommitted;
this._iTransaction=this.CreateISession().BeginTransaction(isolationLevel);
}

//DAO层:事务回滚
publicvirtualvoidRollbackTransation()
{
this._iTransaction.Rollback();
}
guilin_gavin 2009-01-05
  • 打赏
  • 举报
回复
学习
gtiroy 2009-01-05
  • 打赏
  • 举报
回复
OracleTransaction tran = conn.BeginTransaction(IsolationLevel.ReadCommitted);

可以设置事务完成前可见还是不可见的。
gtiroy 2009-01-05
  • 打赏
  • 举报
回复
using (OracleConnection conn = new OracleConnection(OracleHelper.Conn_OracleStrings))
{
OracleParameter[] para = this.SendMessageMainPara(messageMain, Sid);

//读序列(只有主表度,其他表都自动生成)
conn.Open();
OracleTransaction tran = conn.BeginTransaction(IsolationLevel.ReadCommitted);

string strText = Sql_insert_Send + Sql_insert_SendPara;
//做事务处理。
try
{
OracleHelper.ExecuteNonQuery(tran, CommandType.Text, Sql_insert_SendMessage, para);

tran.Commit();

}
catch (Exception ex)
{
tran.Rollback();
throw ex;
}
finally
{
conn.Close();
}

}
AssetSystem 2009-01-05
  • 打赏
  • 举报
回复
因为是多层的架构,代码太复杂,我试试看能不能整理出来,恐怕很难!
越黎越为食 2009-01-05
  • 打赏
  • 举报
回复
把程序贴出来嘛
AssetSystem 2009-01-05
  • 打赏
  • 举报
回复
顺便介绍下开发环境:
开发工具:vs2008
数据库:oracle 10g
DAO: nhibernate
架构:b/s
操作系统: winxp sp2

AssetSystem 2009-01-05
  • 打赏
  • 举报
回复
肯定是同一connection,而且是在异常出现后rollback的。
而且现在更奇怪的是:同样的程序、连接同样的ORACLE数据库到另一个同事机器开发调式一切正常,回滚得很好,而且仅同一会话可以看见插入但未提交的记录。很不解,不知道windows有什么设置让事务是否启用,但按理说这种插入记录是数据库的事情,数据库事务应该是数据库控制才对!晕菜了!
ximi82878 2009-01-05
  • 打赏
  • 举报
回复
up
烈火蜓蜻 2009-01-05
  • 打赏
  • 举报
回复
我估计搂主的程序, 是用了不同的 Connection 对象造成这个问题的

你要把你事务内的SQL语句执行,都用同一个SqlTransaction对象也完成,

(以上是针对在C#内部事务,而不是存储过程)
gouyear 2009-01-05
  • 打赏
  • 举报
回复
学习
soaringbird 2009-01-05
  • 打赏
  • 举报
回复
你所说的只是其他会话看到脏数据而已,而不是能不能回滚的事。
隔离级别只对本会话有效,如果别的会话设置成了允许脏读的话,还是可以看到事务中未提交的数据的。
能不能回滚要执行一下回滚试试才知道,数据消失不了的才是不能回滚。
gouhan02 2009-01-05
  • 打赏
  • 举报
回复
怎么会回滚不了,找个例子看看
你是不是先commit了?
加载更多回复(3)

111,130

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧