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

时间:2021-08-16 03:10:54

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

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

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

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

1)实体

         /// <summary>
/// 订单表
/// </summary>
public class Orders
{
public Int32 Id { get; set; }
public String Name{get;set;}
}
/// <summary>
/// 订单详细表
/// </summary>
public class OrderDetail
{
public Int32 Id { get; set; }
public Int32 OrderId { get; set; }
public String Name { get; set; }
}

2)sql语句

 /*订单*/
CREATE TABLE Orders
(
PRIMARY KEY(Id),
Id int,
Name varchar(20)
)
/*订单详细*/
CREATE TABLE OrderDetail
(
PRIMARY KEY(Id),
Id INT,
OrderId INT,
Name varchar(20)
)

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

     public class Repository
{
public const String connStr = "server=;database=TestDB;user id=;pwd="; /// <summary>
/// 添加订单
/// </summary>
/// <param name="order">订单信息</param>
/// <param name="tran">事务</param>
/// <returns>受影响的数量</returns>
public Int32 AddOrder(Orders order, SqlTransaction tran = null)
{
StringBuilder sb = new StringBuilder();
SqlParameter parId = new SqlParameter("@Id", SqlDbType.Int);
SqlParameter parName = new SqlParameter("@Name", SqlDbType.VarChar, ); parId.Value = order.Id;
parName.Value = order.Name;
sb.Append(" insert into Orders(Id,Name) values(@Id,@Name)"); if (tran == null)
return SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sb.ToString(), parId, parName);
return SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sb.ToString(), parId, parName);
} /// <summary>
/// 更新订单
/// </summary>
/// <param name="order">订单信息</param>
/// <param name="tran">事务</param>
/// <returns>受影响的数量</returns>
public Int32 UpdateOrder(Orders order, SqlTransaction tran = null)
{
StringBuilder sb = new StringBuilder();
SqlParameter parId = new SqlParameter("@Id", SqlDbType.Int);
SqlParameter parName = new SqlParameter("@Name", SqlDbType.VarChar, ); parId.Value = order.Id;
parName.Value = order.Name;
sb.Append(" update Orders set Name=@Name where Id=@id "); if (tran == null)
return SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sb.ToString(), parId, parName);
return SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sb.ToString(), parId, parName);
} /// <summary>
/// 添加订单详细
/// </summary>
/// <param name="order">订单详细信息</param>
/// <param name="tran">事务</param>
/// <returns>受影响的数量</returns>
public Int32 AddOrderDetail(OrderDetail orderDetail, SqlTransaction tran = null)
{
StringBuilder sb = new StringBuilder();
SqlParameter parId = new SqlParameter("@Id", SqlDbType.Int);
SqlParameter parOrderId = new SqlParameter("@OrderId", SqlDbType.Int);
SqlParameter parName = new SqlParameter("@Name", SqlDbType.VarChar, ); parId.Value = orderDetail.Id;
parOrderId.Value = orderDetail.OrderId;
parName.Value = orderDetail.Name;
sb.Append(" insert into OrderDetail(Id,OrderId,Name) values(@Id,@OrderId,@Name)"); if (tran == null)
return SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sb.ToString(), parId, parOrderId, parName);
return SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sb.ToString(), parId, parOrderId, parName);
} /// <summary>
/// 更新订单详细
/// </summary>
/// <param name="order">订单详细信息</param>
/// <param name="tran">事务</param>
/// <returns>受影响的数量</returns>
public Int32 UpdateOrderDetail(OrderDetail orderDetail, SqlTransaction tran = null)
{
StringBuilder sb = new StringBuilder();
SqlParameter parId = new SqlParameter("@Id", SqlDbType.Int);
SqlParameter parOrderId = new SqlParameter("@OrderId", SqlDbType.Int);
SqlParameter parName = new SqlParameter("@Name", SqlDbType.VarChar, ); parId.Value = orderDetail.Id;
parOrderId.Value = orderDetail.OrderId;
parName.Value = orderDetail.Name;
sb.Append(" update OrderDetail set Name=@Name,OrderId=@OrderId where Id=@id "); if (tran == null)
return SqlHelper.ExecuteNonQuery(connStr, CommandType.Text, sb.ToString(), parId, parOrderId, parName);
return SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sb.ToString(), parId, parOrderId, parName);
}
}

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

     /// <summary>
/// 事务类
/// </summary>
public class SqlTran
{
/// <summary>
/// 执行事务(单一方法)
/// </summary>
/// <typeparam name="T">实体</typeparam>
/// <param name="method">要执行的方法(SqlTransaction 默认传入为null)</param>
/// <param name="obj1">参数值</param>
/// <returns></returns>
public static Int32 ExecuteTran<T>(Func<T, SqlTransaction, Int32> method, T obj1)
where T : new()
{
Int32 count = ;
SqlConnection conn = null;
SqlTransaction tran = null;
try
{
conn = new SqlConnection(Repository.connStr);
conn.Open();
tran = conn.BeginTransaction(); count += method(obj1, tran); //执行方法 tran.Commit();
return count;
}
catch (Exception ex)
{
tran.Rollback();
return -;
}
finally
{
if (tran != null)
tran.Dispose();
if (conn != null)
{
conn.Close();
conn.Dispose();
}
} } /// <summary>
/// 执行事务(事务中存在两个方法)
/// </summary>
/// <typeparam name="T">实体</typeparam>
/// <param name="method">要执行的方法(SqlTransaction 默认传入为null)</param>
/// <param name="obj1">参数值</param>
/// <returns></returns>
public static Int32 ExecuteTran<T>(Func<T, SqlTransaction, Int32> method1, Func<T, SqlTransaction, Int32> method2, T obj1, T obj2)
where T : new()
{
Int32 count = ;
SqlConnection conn = null;
SqlTransaction tran = null;
try
{
conn = new SqlConnection(Repository.connStr);
conn.Open();
tran = conn.BeginTransaction(); count += method1(obj1, tran);
count += method2(obj2, tran); tran.Commit();
return count;
}
catch (Exception ex)
{
tran.Rollback();
return -;
}
finally
{
if (tran != null)
tran.Dispose();
if (conn != null)
{
conn.Close();
conn.Dispose();
}
} } /// <summary>
/// 执行事务(同实体事务执行【方法不一定相同】)
/// </summary>
/// <typeparam name="T">实体</typeparam>
/// <param name="method">要执行的方法(SqlTransaction 默认传入为null)</param>
/// <param name="obj1">参数值</param>
/// <returns></returns>
public static Int32 ExecuteTran<T>(IList<Func<T, SqlTransaction, Int32>> methods, IList<T> objs)
where T : new()
{
Int32 count = ;
SqlConnection conn = null;
SqlTransaction tran = null;
try
{
conn = new SqlConnection(Repository.connStr);
conn.Open();
tran = conn.BeginTransaction();
if (methods.Count() != objs.Count())
return -; //异常 for (int i = ; i < objs.Count; i++)
count += methods[i](objs[i], tran); tran.Commit();
return count;
}
catch (Exception ex)
{
tran.Rollback();
return -;
}
finally
{
if (tran != null)
tran.Dispose();
if (conn != null)
{
conn.Close();
conn.Dispose();
}
} }
}

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

         public void Test()
{
Repository repository = new Repository();
Orders order1 = new Orders() { Id = , Name = "name1" };
Orders order2 = new Orders() { Id = , Name = "name2" };
Orders order3 = new Orders() { Id = , Name = "name3" };
Orders order4 = new Orders() { Id = , Name = "name4" };
Orders order5 = new Orders() { Id = , Name = "name5" };
OrderDetail orderDetail1 = new OrderDetail() { Id = , OrderId = , Name = "namedetail1" };
OrderDetail orderDetail2 = new OrderDetail() { Id = , OrderId = , Name = "namedetail2" }; SqlTran.ExecuteTran<Orders>(repository.AddOrder, order1);
SqlTran.ExecuteTran<OrderDetail>(repository.AddOrderDetail, orderDetail1); //泛型的好处,可以少写代码 SqlTran.ExecuteTran<Orders>(repository.AddOrder, repository.AddOrder, order2, order3); //同方法,同实体类型
order1.Name = "orderName1update";
SqlTran.ExecuteTran<Orders>(repository.AddOrder, repository.UpdateOrder, order4, order1); //不同方法,同实体类型 List<Func<Orders, SqlTransaction, Int32>> list = new List<Func<Orders, SqlTransaction, Int32>>(); //多方法(混合更新和添加)
List<Orders> listObj = new List<Orders>();
list.Add(repository.UpdateOrder);
order1.Name = "orderName1updatet";
listObj.Add(order1);
list.Add(repository.AddOrder);
listObj.Add(order5);
SqlTran.ExecuteTran<Orders>(list, listObj);
}

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

如何实现SQL事务的提交,又不对外进行污染的更多相关文章

  1. 如何实现SQL事务的提交,又不对外进行污染&lpar;2&rpar;

    紧接着上文,这里主要记录事务操作,实现多实体的功能 在SqlTran类中添加方法如下: 1.两个不同实体类型的事务方法: /// <summary> /// 执行事务(事务中不同实体) / ...

  2. 30分钟全面解析-SQL事务&plus;隔离级别&plus;阻塞&plus;死锁

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化.  本系列主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础] ...

  3. sql事务(Transaction)用法介绍及回滚实例

    sql事务(Transaction)用法介绍及回滚实例 事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务, S ...

  4. 存储过程中使用事务&comma;sql server 事务&comma;sql事务

    一.存储过程中使用事务的简单语法       在存储过程中使用事务时非常重要的,使用数据可以保持数据的关联完整性,在Sql server存储过程中使用事务也很简单,用一个例子来说明它的语法格式: 代码 ...

  5. SQL事务

    一.事务概念    事务是一种机制.是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行.因此事务是一个不可分割的工作逻辑单元.在数据库系统上执行并发操作时事务是作为最小的 ...

  6. SQL—— 事务

    SQL 事务: 1.  定义: 事务是作为单个逻辑单元执行的一系列操作. 多个操作作为一个整体向系统提交,要么执行.要么都不执行,事务是一个不可分割的工作逻辑单元.这特别适用于多用户同时操作的数据通信 ...

  7. SQL事务隔离级别

    数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况. 更新丢失(Lost update) 两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修 ...

  8. SQL事务与并发

    1.Transaction(事务)是什么: 事务是作为单一工作单元而执行的一系列操作.包括增删查改. 2.事务的种类: 事务分为显示事务和隐式事务: 隐式事务:就是平常我们使用每一条sql 语句就是一 ...

  9. SQL 事务及实例演示

    简介 事务,英文名称是transaction.是在对数据库进行管理操作过程中一个逻辑单位,由有限的操作序列构成. 其实这个概念很好懂,简单理解就是:事务就是在使用数据库中的一个操作,由一些操作放到一起 ...

随机推荐

  1. Windows8&period;1画热度图 - 坑

    想要的效果 如上是silverlight版本.原理是设定一个调色板,为256的渐变色(存在一个png文件中,宽度为256,高度为1),然后针对要处理的距离矩阵图形,取图片中每个像素的Alpha值作为索 ...

  2. win7&comma;ubuntu双系统——重装win7后如何恢复ubuntu引导

    磁盘分区——windows 7自带分区工具实现 磁盘分区——PQ硬盘分区魔术师 win7,ubuntu双系统的安装——正式安装 win7,ubuntu双系统的安装——卸载ubuntu 讲述了我的  w ...

  3. oracle 10g 学习之基本 SQL SELECT 语句(4)

    本篇文章中,对于有的和MSSQL Server相同的语法我就没有再写了,这里我只写Oracle和MSSQL Server有点不同的 定义空值 l  空值是无效的,未指定的,未知的或不可预知的值 l  ...

  4. jq实现图像旋转木马&colon;轮焦点&plus;关于控制&plus;自己主动旋转木马

    资源:http://www.ido321.com/862.html html代码: 1: <!DOCTYPE html> 2: <html lang="en"&g ...

  5. ThinkPHP3&period;2基础知识(二)

    1.单入口模式的好处: 安全,灵活.可集中进行安全处理,访问统计等统一控制. 2.入口文件中为什么要判断PHP版本,TP要求PHP的版本是什么? 因为ThinkPHP3.2版本只能在PHP版本5.3. ...

  6. 无法修改linux&sol;ubuntu密码&lpar;Authentication token manipulation error &rpar;问题解决过程【转】

    转自:https://blog.csdn.net/caizi001/article/details/38659189 Vmware虚拟机里的ubunut系统长期不用,密码忘记了,无奈只能通过slax ...

  7. POJ 3078 - Shuffle&&num;39&semi;m Up - &lbrack;模拟题&rsqb;

    题目链接:http://poj.org/problem?id=3087 Description A common pastime for poker players at a poker table ...

  8. putty之pscp上传文件

    控制台下打开pscp可执行文件 命令 >pscp -i 证书名 -r 要上传的文件 root@服务器路径:/opt

  9. usb-cam &lpar;3&rpar;摄像机标定文件-ORB-SLAM标定文件

    http://www.luohanjie.com/2017-04-05/the-problem-of-calibration-data-in-orb-slam2.html ORB_SLAM2中标定数据 ...

  10. 【Linux】Centos6&period;8下一键安装Lamp环境

    [下载地址] 以下三种都是快捷安装环境的工具,都提供相应的脚本,原理都相同,一个会了其他的也就都会了,我用的比较多的会是lnmp和oneinstack,最近在用的都是oneinstack,挺好用的. ...