0
点赞
收藏
分享

微信扫一扫

将不确定变为确定~transactionscope何时提升为分布式事务?(sql2005数据库解决提升到MSDTC的办法)

​​回到目录​​

对于transactionscope不了解的同学,可以看我的相关文章

 

第二十六回   ​​将不确定变为确定~transactionscope何时提升为分布式事务?​​

第二十七回   ​​将不确定变为确定~transactionscope何时提升为分布式事务~续​​

第二十八回   ​​将不确定变为确定~transactionscope何时提升为分布式事务~再续(避免引起不必要的MSDTC)​​

第二十九回   ​​将不确定变为确定~transactionscope何时提升为分布式事务~大结局​​

​​第三十七回   将不确定变为确定~transactionscope何时提升为分布式事务~SQL2005与SQL2008不同​​

声明:

对于这种事务,如果希望程序出错自动回滚,必须将异常throw出来,不能愉愉的用日志记录!

测试:

对于sql2008已经很好的支持了transactionscope,而对于sql2005来说,支持的不是很好,它将多个savechanges()方法提升为分布式事务msdtc,它不管你是否为一个数据库,真是无奈了!还好,最好找到了解决方法,下面图所示,将多个insert,update包裹到一个transactionscope里,所产生的结果如下:

将不确定变为确定~transactionscope何时提升为分布式事务?(sql2005数据库解决提升到MSDTC的办法)_分布式事务

简单来说,就是sp_reset_connection重新使用一次SQL链接时,你的事务里的代码是被包裹在一起发送过来的,这时,如果有一条SQL语句出现异常,整个包会发生callback!

将不确定变为确定~transactionscope何时提升为分布式事务?(sql2005数据库解决提升到MSDTC的办法)_sql_02

上面图中,只要有一条语句出现SQL异常,都会发生回滚,从而保证了数据的完整性。

当然,我们的计算机中,并没有开启msdtc服务,有图有真像

将不确定变为确定~transactionscope何时提升为分布式事务?(sql2005数据库解决提升到MSDTC的办法)_数据_03

前提:Db数据上下文对象必须与action指向的方法体里的上下文是同一个。

相关原始代码为:

var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)Db).ObjectContext;
try
{
objectContext.Connection.Open();
using (TransactionScope trans = new TransactionScope())
{
insert1();
insert2();
}
}
catch (Exception)
{

throw;
}
finally
{
objectContext.Connection.Close();
}

OK,我们将上面代码进行一个封装,让它访问起来更方便一些,看代码:

/// <summary>
/// Author:zhang.zhanling
/// 对TransactionScope,让它对同一个数据库不产生msdtc服务
/// </summary>
public class TransactionScopeNoMsdtc
{
/// <summary>
/// 产生包裹事务
/// </summary>
/// <param name="db">数据上下文</param>
/// <param name="isOutermost">是否为最外层,默认为false</param>
/// <param name="action">处理代码块</param>
public static void UsingNoMsdtc(DbContext db, bool isOutermost, Action action)
{
var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)db).ObjectContext;
try
{
if (objectContext.Connection.State == System.Data.ConnectionState.Closed)
objectContext.Connection.Open();
using (TransactionScope trans = new TransactionScope())
{
action();
trans.Complete();
}
}
finally
{
if (isOutermost)//如果是最外层事务,而将连接关闭
objectContext.Connection.Close();
}
}
/// <summary>
/// 产生包裹事务,它不是最外层的,如果是最外层的需要调用其它重载
/// </summary>
/// <param name="db"></param>
/// <param name="action"></param>
public static void UsingNoMsdtc(DbContext db, Action action)
{
UsingNoMsdtc(db, false, action);
}
}

 

在使用时,我们可以这样来做,不用TransactionScope,而是用TransactionScopeNoMsdtc呵呵。

{
insert1();
insert2();
});

感谢阅读!

​​回到目录​​

作者:仓储大叔,张占岭,
荣誉:微软MVP



举报

相关推荐

0 条评论