如何实现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 }
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 )
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 }
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 }
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 }
这里只是对单一实体进行处理,下文继续对多实体进行处理
注:SqlHelper为微软的简单类文件,可以在网上自行下载
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。