如何实现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.是在对数据库进行管理操作过程中一个逻辑单位,由有限的操作序列构成. 其实这个概念很好懂,简单理解就是:事务就是在使用数据库中的一个操作,由一些操作放到一起 ...
随机推荐
- cf C. Valera and Elections
http://codeforces.com/contest/369/problem/C 先见边,然后dfs,在回溯的过程中,如果在这个点之后有多条有问题的边,就不选这个点,如果没有而且连接这个点的边还 ...
- BZOJ 2732 射箭
http://www.lydsy.com/JudgeOnline/problem.php?id=2732 题意:给你n个靶子,让你求是否有一个经过原点的抛物线经过最多的前k个靶子,求出最大的k 思路: ...
- [LeetCode 122] - 买入与卖出股票的最佳时机II(Best Time to Buy and Sell Stock II)
问题 假设你有一个数组,其中的第i个元素表示一只股票在第i天的价格. 设计一个算法找出最大的利润值.你可以进行任意多次的交易(即多次的卖出并买入一份股票).你不能在同一时间进行多次交易(即你必须在再次 ...
- MCS-51单片机实用子程序库
目前已有若干版本的子程序库公开发表,它们各有特色.本程序库中的开平方算法为快速逼近算法,它能达到牛顿迭代法同样的精度,而速度加快二十倍左右,超过双字节定点除法的速度. 本子程序库对<单片机应用程 ...
- 一些pyhon的学习资料
一直没有时间学习python,都说python语法简洁优美.但是我看它的语法还是不爽啊,没C/C++好阅读.但是C/C++又必须了解底层的计算机模型.着实会门槛高一些.特别是C++,对于我来说简直就是 ...
- netcat
一.概述 netcat是网络工具中的瑞士军刀,它能通过TCP和UDP在网络中读写数据.通过与其他工具结合和重定向,你可以在脚本中以多种方式使用它.使用netcat命令所能完成的事情令人惊讶.netca ...
- BZOJ2212: [Poi2011]Tree Rotations
2212: [Poi2011]Tree Rotations Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 391 Solved: 127[Submi ...
- stardict词典(星际译王)
sudo apt-get install stardict 下载词库: http://abloz.com/huzheng/stardict-dic/zh_CN/ 把下载的压缩包解压,以a为例cd /u ...
- Android Fragment详解(三): 实现Fragment的界面
为fragment添加用户界面: Fragment一般作为activity的用户界面的一部分,把它自己的layout嵌入到activity的layout中. 一个 要为fragment提供layout ...
- io系统
一.浅谈io系统 io系统的结构化思想是:输入-转换流-装饰器-输出. 对于字节流来说,常见的结构类为: package com.handchina.yunmart.middleware.servic ...