网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > .Net编程 > 正文

如何在项目中应用LinqToSql数据库事务

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

本文主要涉及LinqToSql数据库事务相关,文章不足之处,欢迎您指出。

     一、回顾T-SQL中的事务机制:

代码如下:

  1. /*加入事务机制后的存储过程*/ 
  2.  create procedure sp_example 
  3.   @param1 int = null
  4.   @param2 nvarchar(20) = null 
  5.  as 
  6.    begin tran tranName /*sql 事务的加入*/ 
  7.    insert into table0 (col1,col2,col3) values ('value1','value2','value3'
  8.    update table1 set column1 = @param1 where 1=1 
  9.    --删除table2中一条已经被其他外键表引用的记录,此时会报sql引用错误 
  10.    delete from table2 where column3 = @param1     
  11.    insert into table3 (col1,col2) values ('value1','value2'
  12.    if(@@error =0) 
  13.       commit tran tranName 
  14.    else 
  15.      rollback tran tranName 
  16.  go 

以上代码是一个具备事务机制的简单存储过程,需要指出的是当上述代码执行到第十行时,此时如果该存储过程未加入事务机制那么势必会导致第10行之前已经被影响的数据库记录也不会被还原(rollback)。这样的代码是我们不想见到的,所以事务在复杂的商业逻辑中保持数据的完整性还是尤为重要的。

    二、LinqToSql 中的SubmitChanges内置事务机制:

众所周知LinqToSql 中我们的事务机制代码变的相对简单了,如以下代码:

  1. public bool DeleteDepartment(int departmentId) 
  2.         { 
  3.             try 
  4.             { 
  5.                 DataContext.SystemUser.DeleteOnSubmit( 
  6.                                    DataContext.SystemUser.FirstOrDefault(u => u.DepartmentID == departmentId)); 
  7.  
  8.                 DataContext.Department.DeleteOnSubmit( 
  9.                                     DataContext.Department.FirstOrDefault(f => f.DepartmentID == departmentId)); 
  10.  
  11.                 //事务机制被封装到SubmitChanges方法内 
  12.                  DataContext.SubmitChanges(); 
  13.  
  14.                 return true
  15.             } 
  16.             catch 
  17.             { 
  18.                 return false
  19.             } 
  20.         } 

上诉代码很容易理解,在LinqToSql 为了删除一条部门记录。我们首选要删除该部门被引用的外键表记录这里是员工表,(上诉代码只是为举例用,实际开发中是不会有此种业务的)当外键记录都删除成功后代码执行到第8行,这时才能能删除部门对象。否则报SqlException外键引用无法删除部门记录。我们唯一需要做的只是将 DataContext.SubmitChanges();这句放在所有Linq操作数据库语句之后这样就可以调用数据库事务机制了。比如当第5行代码执行时SystemUser还被Order表引用。当SubmitChanges执行时会自动调用transaction.Rollback()方法回滚SubmitChanges()之前的所有被影响的数据库记录,详情请阅Reflector。

   三、在LinqToSql中SubmitChange内置事务机制无法满足的业务场景:

      当程序需要处理更多更复杂的商业逻辑时,我发现光凭SubmitChange方法自带的事务机制是远远不能满足的。

      该场景描述如下:
       如果为完成某一个特定的业务,需要在程序中使用多次的SubmitChanges方法。比如我们要做一个库存相关业务,该业务是由两张表组成:主表+从表。分别为主表:Depot和从表:DepotDetail 两张表。两张表关系如下:

  当我们通过LinqToSql生成一个库存对象时其实应先生成Depot对象后再将生成Depot对象的DepotID(主键)传递到DepotDetail对象中用于生成库存明细表记录。也就说为了生成库存明细表记录我们必须先生成Depot主表,那样就不得不先调用SubmitChanges方法,当保存DepotDetail对象时还需要再一次调用SubmitChanges()方法。因为调用了多次SubmitChanges方法所以SubmitChanges内置的回滚机制已经不能满足需要了。

  四、TransactionScope的应用:

     我们需要引用.net 的System.Transactions 类库使用TransactionScope类,帮我们更有效的处理数据库事务机制。对TransactionScope进行封装,代码如下:

DBTransactionExtension

  1. public static class DBTransactionExtension 
  2.     public static bool Excute(out string errorMsg, params Action actions) 
  3.     { 
  4.         //使用ReadCommitted隔离级别,保持与Sql Server的默认隔离级别一致 
  5.          return Excute(out errorMsg, IsolationLevel.ReadCommitted, null, actions); 
  6.  
  7.     } 
  8.  
  9.     public static void Excute(out string errorMsg, IsolationLevel level, params Action actions) 
  10.     { 
  11.         Excute(out errorMsg, level, null, actions); 
  12.     } 
  13.  
  14.     public static void Excute(out string errorMsg, int timeOut, params Action actions) 
  15.     { 
  16.         Excute(out errorMsg, IsolationLevel.ReadCommitted, timeOut, actions); 
  17.     } 
  18.  
  19.     public static bool Excute(out string errorMsg, IsolationLevel level, int? timeOut, params Action actions) 
  20.     { 
  21.         errorMsg = ""
  22.         if (actions == null || actions.Length == 0) 
  23.             return false
  24.         TransactionOptions options = new TransactionOptions(); 
  25.  
  26.         options.IsolationLevel = level; //默认为Serializable,这里根据参数来进行调整 
  27.  
  28.         if (timeOut.HasValue) 
  29.  
  30.             options.Timeout = new TimeSpan(0, 0, timeOut.Value); //默认60秒 
  31.  
  32.         using (TransactionScope tran = new TransactionScope(TransactionScopeOption.Required, options)) 
  33.         { 
  34.             try 
  35.             { 
  36.                 Array.ForEach<Action>(actions, action => action()); 
  37.                 tran.Complete(); //通知事务管理器它可以提交事务 
  38.                  return true
  39.             } 
  40.             catch (Exception ex)//回滚事务 
  41.              { 
  42.                 errorMsg = ex.Message; 
  43.                 return false
  44.             } 
  45.         } 
  46.     } 
  47.  

调用DBTransactionExtension代码如下:

  1. private void SaveDepot(Depot depot) 
  2.        { 
  3.            DataContext.Depots.InsertOnSubmit(depot); 
  4.  
  5.            if (false)//TODO:保存库存主表前的逻辑判断,条件不满足时候调用 throw new exception执行TransactionScope回滚。 
  6.                 throw new Exception("自定义错误提示内容,最终由事务获取错误信息后抛给UI"); 
  7.  
  8.            //条件满足则调用SubmitChanges 
  9.            DataContext.SubmitChanges(); 
  10.            DepotDetail depotDetail = new DepotDetail(); 
  11.            depotDetail.DepotID = depot.DepotID; 
  12.            depotDetail.Count = 100; 
  13.  
  14.            DataContext.DepotDetails.InsertOnSubmit(depotDetail); 
  15.            //又调用了一次SubmitChanges 
  16.             DataContext.SubmitChanges(); 
  17.        } 
  18. public Depot InvokeTransaction(Depot depot, out string errorMsg) 
  19.        { 
  20.            try 
  21.            { 
  22.                DBTransactionExtension.Excute(out errorMsg, () => SaveDepot(depot)); 
  23.                return depot; 
  24.            } 
  25.            catch (Exception ex) 
  26.            { 
  27.                errorMsg = ex.Message; 
  28.                return null
  29.            } 
  30.        } 

根据上述调用方法,我们已经可以在LinqToSql中灵活的使用数据库事务了。

  五、TransactionScope类使用的注意事项:

    使用TransactionScope时如果调用多次LinqToSql的DataContext对象实例(等同调用多个数据库连接),那么我们必须开启MSDTC否则事务不能正常工作,具体请阅MSDTC开启。注:TransactionScope 适用于多种 Data Provider 比如 oracle 、OleDB、ODBC等。
   最后希望本篇文章能给您带来帮助。

  • 下一篇资讯: Asp.net中的认证与授权
  • 设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
    版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师