如何实现SQL事务的提交,又不对外进行污染
一、以下是本人的一点思路:
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事务的提交,又不对外进行污染的更多相关文章
- 如何实现SQL事务的提交,又不对外进行污染(2)
紧接着上文,这里主要记录事务操作,实现多实体的功能 在SqlTran类中添加方法如下: 1.两个不同实体类型的事务方法: /// <summary> /// 执行事务(事务中不同实体) / ...
- 30分钟全面解析-SQL事务+隔离级别+阻塞+死锁
以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化. 本系列主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础] ...
- sql事务(Transaction)用法介绍及回滚实例
sql事务(Transaction)用法介绍及回滚实例 事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务, S ...
- 存储过程中使用事务,sql server 事务,sql事务
一.存储过程中使用事务的简单语法 在存储过程中使用事务时非常重要的,使用数据可以保持数据的关联完整性,在Sql server存储过程中使用事务也很简单,用一个例子来说明它的语法格式: 代码 ...
- SQL事务
一.事务概念 事务是一种机制.是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行.因此事务是一个不可分割的工作逻辑单元.在数据库系统上执行并发操作时事务是作为最小的 ...
- SQL—— 事务
SQL 事务: 1. 定义: 事务是作为单个逻辑单元执行的一系列操作. 多个操作作为一个整体向系统提交,要么执行.要么都不执行,事务是一个不可分割的工作逻辑单元.这特别适用于多用户同时操作的数据通信 ...
- SQL事务隔离级别
数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况. 更新丢失(Lost update) 两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修 ...
- SQL事务与并发
1.Transaction(事务)是什么: 事务是作为单一工作单元而执行的一系列操作.包括增删查改. 2.事务的种类: 事务分为显示事务和隐式事务: 隐式事务:就是平常我们使用每一条sql 语句就是一 ...
- SQL 事务及实例演示
简介 事务,英文名称是transaction.是在对数据库进行管理操作过程中一个逻辑单位,由有限的操作序列构成. 其实这个概念很好懂,简单理解就是:事务就是在使用数据库中的一个操作,由一些操作放到一起 ...
随机推荐
- Android ActionBar 返回为NULL
AndroidBar返回为NULL.是因为values-v11和values-v14下面的style的主题的设置的原因. 在SDK 11的设备上,会使用第二处,SDK 14会使用第三处. 只需要将三个 ...
- android 数据存储的几种方式
总体的来讲,数据存储方式有三种:一个是文件,一个是数据库,另一个则是网络.其中文件和数据库可能用的稍多一些,文件用起来较为方便,程序可以自己定义格式:数据库用起稍烦锁一些,但它有它的优点,比如在海量数 ...
- Javascript 原型注意事项
function abc() {} abc.prototype.xx = { name: "keatkeat" } var x = new abc(); x.xx.name = & ...
- Powershell创建对象
.Net类型中的方法功能很强大.可以通过类型的构造函数创建新的对象,也可以将已存在的对象转换成指定的类型. 通过New-Object创建新对象 如果使用构造函数创建一个指定类型的实例对象,该类型必须至 ...
- Qt编程之实现属性窗口编辑器
类似于这种: 就是右下角这个框,有属性名字和对应的value编辑. 这个Widget是作为一个QDockWidget被添加到QMainWindow中的.QMainWindow必须要有centralWi ...
- 黑马程序员_Java面向对象1_封装
3.面向对象_封装 3.1面向对象概念 3.1.1理解面向对象 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程:强调的是功能行为(执行者) 面向对象:将功能封装进对象,强调具备了 ...
- cf437D The Child and Zoo
D. The Child and Zoo time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- Bring it on
I am going to open a whole new English Blog here. Most blogs here would be computer technologies, in ...
- c语言结构体4之结构体引用
struct mystruct{ char str[23];}; 1结构体变量不能整体引用 struct data m: printf("%s",m);//m是结构体变量 2 st ...
- 传智播客学习之HTML基础语法
一.基本格式 1.不用区分大小写. 2.HTML代码由<html>开始</html>结束.里面由头部分<head></head>和体部分<body ...