• 如何实现SQL事务的提交,又不对外进行污染


    一、以下是本人的一点思路:

    1、在事务方法中,参数运用委托Func,选用Func 的原因是多入参,单一出参
    2、事务传参运用泛型,选用泛型的原因是可以减少代码量,类型安全

    二、说明中涉及4个类:
    1、Orders、OrderDetail:订单实体,订单详细实体
    2、Repository:进行数据操作
    3、SqlTran:事务处理方法(前期的时候方法比较多,后期就会共用【泛型好处】)

    三、步骤
    1、创建实体(创建对应的数据库语句)

        1)实体

     1         /// <summary>
     2         /// 订单表
     3         /// </summary>
     4         public class Orders
     5         {
     6             public Int32 Id { get; set; }
     7             public String Name{get;set;}
     8         }
     9         /// <summary>
    10         /// 订单详细表
    11         /// </summary>
    12         public class OrderDetail
    13         {
    14             public Int32 Id { get; set; }
    15             public Int32 OrderId { get; set; }
    16             public String Name { get; set; }
    17         }
    View Code

       2)sql语句

     1 /*订单*/
     2 CREATE TABLE Orders 
     3 (
     4    PRIMARY KEY(Id),
     5   Id int,
     6   Name varchar(20)
     7 )
     8 /*订单详细*/
     9 CREATE TABLE OrderDetail 
    10 (
    11   PRIMARY KEY(Id),
    12   Id INT,
    13   OrderId INT,
    14   Name varchar(20)
    15 )
    View Code

    2、写增、改方法,作为事务的参数(较简单,用于进行测试)

     1     public class Repository
     2     {
     3         public const String connStr = "server=;database=TestDB;user id=;pwd=";
     4 
     5         /// <summary>
     6         /// 添加订单
     7         /// </summary>
     8         /// <param name="order">订单信息</param>
     9         /// <param name="tran">事务</param>
    10         /// <returns>受影响的数量</returns>
    11         public Int32 AddOrder(Orders order, SqlTransaction tran = null)
    12         {
    13             StringBuilder sb = new StringBuilder();
    14             SqlParameter parId = new SqlParameter("@Id", SqlDbType.Int);
    15             SqlParameter parName = new SqlParameter("@Name", SqlDbType.VarChar, 25);
    16 
    17             parId.Value = order.Id;
    18             parName.Value = order.Name;
    19             sb.Append(" insert into Orders(Id,Name) values(@Id,@Name)");
    20 
    21             if (tran == null)
    22                 return SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sb.ToString(), parId, parName);
    23             return SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sb.ToString(), parId, parName);
    24         }
    25 
    26         /// <summary>
    27         /// 更新订单
    28         /// </summary>
    29         /// <param name="order">订单信息</param>
    30         /// <param name="tran">事务</param>
    31         /// <returns>受影响的数量</returns>
    32         public Int32 UpdateOrder(Orders order, SqlTransaction tran = null)
    33         {
    34             StringBuilder sb = new StringBuilder();
    35             SqlParameter parId = new SqlParameter("@Id", SqlDbType.Int);
    36             SqlParameter parName = new SqlParameter("@Name", SqlDbType.VarChar, 25);
    37 
    38             parId.Value = order.Id;
    39             parName.Value = order.Name;
    40             sb.Append(" update Orders set Name=@Name where Id=@id ");
    41 
    42             if (tran == null)
    43                 return SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sb.ToString(), parId, parName);
    44             return SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sb.ToString(), parId, parName);
    45         }
    46 
    47         /// <summary>
    48         /// 添加订单详细
    49         /// </summary>
    50         /// <param name="order">订单详细信息</param>
    51         /// <param name="tran">事务</param>
    52         /// <returns>受影响的数量</returns>
    53         public Int32 AddOrderDetail(OrderDetail orderDetail, SqlTransaction tran = null)
    54         {
    55             StringBuilder sb = new StringBuilder();
    56             SqlParameter parId = new SqlParameter("@Id", SqlDbType.Int);
    57             SqlParameter parOrderId = new SqlParameter("@OrderId", SqlDbType.Int);
    58             SqlParameter parName = new SqlParameter("@Name", SqlDbType.VarChar, 25);
    59 
    60             parId.Value = orderDetail.Id;
    61             parOrderId.Value = orderDetail.OrderId;
    62             parName.Value = orderDetail.Name;
    63             sb.Append(" insert into OrderDetail(Id,OrderId,Name) values(@Id,@OrderId,@Name)");
    64 
    65             if (tran == null)
    66                 return SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sb.ToString(), parId, parOrderId, parName);
    67             return SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sb.ToString(), parId, parOrderId, parName);
    68         }
    69 
    70         /// <summary>
    71         /// 更新订单详细
    72         /// </summary>
    73         /// <param name="order">订单详细信息</param>
    74         /// <param name="tran">事务</param>
    75         /// <returns>受影响的数量</returns>
    76         public Int32 UpdateOrderDetail(OrderDetail orderDetail, SqlTransaction tran = null)
    77         {
    78             StringBuilder sb = new StringBuilder();
    79             SqlParameter parId = new SqlParameter("@Id", SqlDbType.Int);
    80             SqlParameter parOrderId = new SqlParameter("@OrderId", SqlDbType.Int);
    81             SqlParameter parName = new SqlParameter("@Name", SqlDbType.VarChar, 25);
    82 
    83             parId.Value = orderDetail.Id;
    84             parOrderId.Value = orderDetail.OrderId;
    85             parName.Value = orderDetail.Name;
    86             sb.Append(" update OrderDetail set Name=@Name,OrderId=@OrderId  where Id=@id ");
    87 
    88             if (tran == null)
    89                 return SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sb.ToString(), parId, parOrderId, parName);
    90             return SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sb.ToString(), parId, parOrderId, parName);
    91         }
    92     }
    View Code

    3、写事务方法,参数为委托方法Func
    (1)用逻辑方法作为参数进行传递,
    (2)事务处理、数据库连接都在事务方法中进行处理
    (3)运用泛型,减少代码量,类型安全

      1     /// <summary>
      2     /// 事务类
      3     /// </summary>
      4     public class SqlTran
      5     {
      6         /// <summary>
      7         /// 执行事务(单一方法)
      8         /// </summary>
      9         /// <typeparam name="T">实体</typeparam>
     10         /// <param name="method">要执行的方法(SqlTransaction 默认传入为null)</param>
     11         /// <param name="obj1">参数值</param>
     12         /// <returns></returns>
     13         public static Int32 ExecuteTran<T>(Func<T, SqlTransaction, Int32> method, T obj1)
     14             where T : new()
     15         {
     16             Int32 count = 0;
     17             SqlConnection conn = null;
     18             SqlTransaction tran = null;
     19             try
     20             {
     21                 conn = new SqlConnection(Repository.connStr);
     22                 conn.Open();
     23                 tran = conn.BeginTransaction();
     24 
     25                 count += method(obj1, tran);          //执行方法
     26 
     27                 tran.Commit();
     28                 return count;
     29             }
     30             catch (Exception ex)
     31             {
     32                 tran.Rollback();
     33                 return -1;
     34             }
     35             finally
     36             {
     37                 if (tran != null)
     38                     tran.Dispose();
     39                 if (conn != null)
     40                 {
     41                     conn.Close();
     42                     conn.Dispose();
     43                 }
     44             }
     45 
     46         }
     47 
     48         /// <summary>
     49         /// 执行事务(事务中存在两个方法)
     50         /// </summary>
     51         /// <typeparam name="T">实体</typeparam>
     52         /// <param name="method">要执行的方法(SqlTransaction 默认传入为null)</param>
     53         /// <param name="obj1">参数值</param>
     54         /// <returns></returns>
     55         public static Int32 ExecuteTran<T>(Func<T, SqlTransaction, Int32> method1, Func<T, SqlTransaction, Int32> method2, T obj1, T obj2)
     56             where T : new()
     57         {
     58             Int32 count = 0;
     59             SqlConnection conn = null;
     60             SqlTransaction tran = null;
     61             try
     62             {
     63                 conn = new SqlConnection(Repository.connStr);
     64                 conn.Open();
     65                 tran = conn.BeginTransaction();
     66 
     67                 count += method1(obj1, tran);
     68                 count += method2(obj2, tran);
     69 
     70                 tran.Commit();
     71                 return count;
     72             }
     73             catch (Exception ex)
     74             {
     75                 tran.Rollback();
     76                 return -1;
     77             }
     78             finally
     79             {
     80                 if (tran != null)
     81                     tran.Dispose();
     82                 if (conn != null)
     83                 {
     84                     conn.Close();
     85                     conn.Dispose();
     86                 }
     87             }
     88 
     89         }
     90 
     91         /// <summary>
     92         /// 执行事务(同实体事务执行【方法不一定相同】)
     93         /// </summary>
     94         /// <typeparam name="T">实体</typeparam>
     95         /// <param name="method">要执行的方法(SqlTransaction 默认传入为null)</param>
     96         /// <param name="obj1">参数值</param>
     97         /// <returns></returns>
     98         public static Int32 ExecuteTran<T>(IList<Func<T, SqlTransaction, Int32>> methods, IList<T> objs)
     99             where T : new()
    100         {
    101             Int32 count = 0;
    102             SqlConnection conn = null;
    103             SqlTransaction tran = null;
    104             try
    105             {
    106                 conn = new SqlConnection(Repository.connStr);
    107                 conn.Open();
    108                 tran = conn.BeginTransaction();
    109                 if (methods.Count() != objs.Count())
    110                     return -1;  //异常
    111 
    112                 for (int i = 0; i < objs.Count; i++)
    113                     count += methods[i](objs[i], tran);
    114 
    115                 tran.Commit();
    116                 return count;
    117             }
    118             catch (Exception ex)
    119             {
    120                 tran.Rollback();
    121                 return -1;
    122             }
    123             finally
    124             {
    125                 if (tran != null)
    126                     tran.Dispose();
    127                 if (conn != null)
    128                 {
    129                     conn.Close();
    130                     conn.Dispose();
    131                 }
    132             }
    133 
    134         }
    135     }
    View Code

    4、调用事务方法进行测试

     1         public void Test()
     2         {
     3             Repository repository = new Repository();
     4             Orders order1 = new Orders() { Id = 1, Name = "name1" };
     5             Orders order2 = new Orders() { Id = 2, Name = "name2" };
     6             Orders order3 = new Orders() { Id = 3, Name = "name3" };
     7             Orders order4 = new Orders() { Id = 4, Name = "name4" };
     8             Orders order5 = new Orders() { Id = 5, Name = "name5" };
     9             OrderDetail orderDetail1 = new OrderDetail() { Id = 1, OrderId = 1, Name = "namedetail1" };
    10             OrderDetail orderDetail2 = new OrderDetail() { Id = 2, OrderId = 1, Name = "namedetail2" };
    11 
    12 
    13             SqlTran.ExecuteTran<Orders>(repository.AddOrder, order1);
    14             SqlTran.ExecuteTran<OrderDetail>(repository.AddOrderDetail, orderDetail1);   //泛型的好处,可以少写代码
    15 
    16             SqlTran.ExecuteTran<Orders>(repository.AddOrder, repository.AddOrder, order2, order3);   //同方法,同实体类型
    17             order1.Name = "orderName1update";
    18             SqlTran.ExecuteTran<Orders>(repository.AddOrder, repository.UpdateOrder, order4, order1); //不同方法,同实体类型
    19 
    20             List<Func<Orders, SqlTransaction, Int32>> list = new List<Func<Orders, SqlTransaction, Int32>>();   //多方法(混合更新和添加)
    21             List<Orders> listObj = new List<Orders>();
    22             list.Add(repository.UpdateOrder);
    23             order1.Name = "orderName1updatet";
    24             listObj.Add(order1);
    25             list.Add(repository.AddOrder);
    26             listObj.Add(order5);
    27             SqlTran.ExecuteTran<Orders>(list, listObj);
    28         }
    View Code

    这里只是对单一实体进行处理,下文继续对多实体进行处理
    注:SqlHelper为微软的简单类文件,可以在网上自行下载

  • 相关阅读:
    SpringBlade 从cookie中获取token
    SpringBlade 可以通过url地址直接访问页面
    Iphone8 在手机上 快捷复制内容 粘贴到电脑上
    其它/编程 删除合同段SQL
    Python 生成周期性波动的数据 可指定数值范围3 预览的html
    Python 生成周期性波动的数据 可指定数值范围3
    ABP application层 httpget
    接口 PostMan put
    Spark报错:Caused by: java.lang.IllegalArgumentException: Compression codec com.hadoop.compression.lzo
    Spark中普通集合与RDD算子的zip()拉链有什么区别
  • 原文地址:https://www.cnblogs.com/liujinwu-11/p/4205696.html
Copyright © 2020-2023  润新知