事务小结
来源:互联网 发布:中小型企业erp软件 编辑:程序博客网 时间:2024/06/06 08:11
事务在时已经接触,但是迟迟没有使用,正好遇到这次项目锻炼机会,使用了一把。
事务
事务(Transaction)是访问,更新数据库中的一个程序执行单元。事务通常由数据库语言或程序的执行所引起,事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
事务是恢复和并发控制的基本单位,事务应该具有4个属性:原子性、一致性、隔离性、持久性,这四个属性通常称为ACID特性。
- 原子性(atomicity),一个事务是一个不可分割的工作单位,事务中包括的多个操作,要么都做,要么都不做。
- 一致性(consistency),事务必须是使数据库从一个一致性状态变到另一个一致性状态,一致性与原子性是密切相关的。
- 隔离性(isolation),即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
连接
好吧,说的有点复杂,事务的目的很简单:你要做一系列的事,要么一口气全部完成;如果中间任何一项出错,大家全部恢复事务前的状态,话说有点“同生共死”的感觉。
不过这个恢复到以前的状态说的有点扯,并不是所有的都能恢复,我在文本框中输入了一些文字,点击按钮触发了一个事务,事务失败了,文本框自动清空了?当然不是,此处的“恢复”指的是对数据库操作的数据恢复。
咱接着说,既然是对数据库的恢复,必然离不开与SQL连接的关联,对,在开发中,谁和谁组成事务的依据就是数据库连接,也就是SqlConnection。
事务
BLL层
转移分数逻辑:先插入再删除。
public bool MoveScore(DataTable dt) { //建立事务 DBTransaction dbTran = new DBTransaction(); //获取连接 SqlConnection sqlConn = dbTran.GetConnection(); SqlTransaction sqlTran = dbTran.GetTransaction(sqlConn); //开启事务 try { HistoryDataDAL historyDAL = new HistoryDataDAL(); ScoreHistoryEntity enScoreHistory = new ScoreHistoryEntity(); ScoresEntity enScore = new ScoresEntity(); //循环执行转移操作 for (int i = 0; i < dt.Rows.Count; i++) { //将表格转换为实体 enScoreHistory.ExamId = dt.Rows[i]["考试ID"].ToString(); enScoreHistory.ExamName = dt.Rows[i]["考试名称"].ToString(); enScoreHistory.Score = dt.Rows[i]["成绩"].ToString(); enScoreHistory.StudentCode = dt.Rows[i]["学号"].ToString(); enScoreHistory.StudentName = dt.Rows[i]["姓名"].ToString(); //转换为分数实体 enScore.ExamId = dt.Rows[i]["考试ID"].ToString(); enScore.StudentId = dt.Rows[i]["学号"].ToString(); //如果哪个学生成绩转移失败,给出提示 if (historyDAL.MoveScore(enScoreHistory, sqlTran, sqlConn) == false || historyDAL.DeleteScoresByStuIdAndExamId(enScore , sqlTran, sqlConn) == false) { throw new Exception("学号为: " + enScoreHistory.StudentCode + "姓名为: " + enScoreHistory.StudentName + "考试为: " + enScoreHistory.ExamName + "的成绩转移失败,请重新转移剩余学生成绩!"); } } sqlTran.Commit(); //执行到这里返回true return true; } catch (Exception moveScoreException) { sqlTran.Rollback(); throw moveScoreException; } finally { sqlConn.Close (); } }
事务类
DBTransaction:这个类主要负责事务的创建、提交、回滚、及关闭数据库连接函数。
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data;using System.Data.SqlClient;public class DBTransaction{ /// <summary> /// 根据配置文件中得变量sqlConn得到连接字符串 /// </summary> private string strCon = ConfigurationManager.ConnectionStrings["sqlConn"].ConnectionString; /// <summary> /// 定义一个连接 /// </summary> private SqlConnection sqlCon; /// <summary> /// 获取数据库连接 /// </summary> /// <returns></returns> public SqlConnection GetConnection() { sqlCon = new SqlConnection(strCon); if (sqlCon.State == ConnectionState.Closed) { sqlCon.Open(); } return sqlCon; } /// <summary> /// 获取事务 /// </summary> /// <returns></returns> public SqlTransaction GetTransaction(SqlConnection conn) { return conn.BeginTransaction(); } /// <summary> /// 提交事务 /// </summary> public void Commit(SqlTransaction sqlTransaction) { sqlTransaction.Commit(); } /// <summary> /// 回滚事务 /// </summary> public void Rollback(SqlTransaction sqlTransaction) { sqlTransaction.Rollback(); } /// <summary> /// 关闭连接 /// </summary> public void Close(SqlConnection conn) { if (conn.State == ConnectionState.Open) { conn.Close(); } }}
DLL层
转移分数方法:在成绩历史表中插入一条成绩数据。
/// <summary>/// 移动成绩到历史表中/// </summary>/// <param name="enScoreHistory">历史成绩试题</param>/// <returns>是否转移成功</returns>public bool MoveScore(ScoreHistoryEntity enScoreHistory, SqlTransaction sqlTran, SqlConnection sqlConn){ try { //SQL语句 string SqlTxt = "insert into TEH_ScoresHistory (StudentCode,StudentName,ExamName,Scores,ExamId) values(@StudentCode,@StudentName,@ExamName,@Scores,@ExamId)"; SqlParameter[] paras = { new SqlParameter("@StudentCode", enScoreHistory.StudentCode), new SqlParameter("@StudentName", enScoreHistory.StudentName), new SqlParameter("@ExamName", enScoreHistory.ExamName), new SqlParameter("@Scores", enScoreHistory.Score), new SqlParameter("@ExamId", enScoreHistory.ExamId), }; //执行结果 int intMoveScore = sqlHelper .ExecNoSelect(SqlTxt, paras, CommandType.Text,sqlConn,sqlTran); //根据返回值判断是否转移成功 if (intMoveScore > 0) { return true; } else { sqlTran.Rollback(); return false; } } catch (Exception MoveScoreException) { sqlTran.Rollback(); throw MoveScoreException; }}
删除原数据方法:在原表中删除该条成绩数据。
/// <summary>/// 根据考试号和学号删除一门成绩/// </summary>/// <param name="enScores">考试实体</param>/// <param name="sqlTran">事务</param>/// <param name="sqlConn">连接</param>/// <returns>是否删除成功</returns>public bool DeleteScoresByStuIdAndExamId(ScoresEntity enScores, SqlTransaction sqlTran, SqlConnection sqlConn){ try { string SqlTxt = "delete from TEB_Scores where ExamId=@ExamId and StudentId=@StudentId"; SqlParameter[] paras = { new SqlParameter("@ExamId", enScores.ExamId), new SqlParameter("@StudentId", enScores.StudentId) }; int intDelExamArr = sqlHelper.ExecNoSelect(SqlTxt, paras, CommandType.Text, sqlConn, sqlTran); //大于零则删除成功 if (intDelExamArr <= 0) { sqlTran.Rollback(); return false; } return true; } catch (Exception DelSocresException) { sqlTran.Rollback(); throw DelSocresException; }}
由代码可以看出,在整个事务中,传递的是同一个数据库连接;因为事务提交或是回滚后,事务已经结束,所以要注意,错误处理时,一定要避免事务的二次提交或回滚。
数据库中的事务
事务同样存在于存储过程等中,以下即是和上面逻辑相同,但是简单化的一个存储过程.
USE BasicDataSystemSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO-- =============================================-- Author:<李达>-- Create date: <2013年3月17日>-- Description:<成绩转移>-- =============================================CREATE PROCEDURE Proc_MoveScores-- 声明学号变量 @StudentCode varchar(50)ASBEGIN-- 启动事务BEGIN TRAN--添加一条成绩到历史表INSERT INTO TEH_ScoresHistory (StudentId) VALUES (@StudentCode)--删除该原成绩DELETE FROM TEB_Scores WHERE StudentId =@StudentCode --出现错误则回滚if @@ERROR <>0ROLLBACK TRAN--否则提交事务ELSECOMMIT TRANENDGO
总结
当然这个事务例子比较简单,参与的逻辑也比较少,但是"麻雀虽小五脏俱全",再复杂的事务也是基于简单之上。
把握不变的,其它任它变。
- 事务小结
- 事务小结
- 事务小结
- Java事务小结
- java 事务小结
- 事务属性小结
- 事务属性小结
- JAVA分布式事务小结
- 数据库操作事务小结
- 事务属性小结
- transaction事务小结
- Spring--事务小结
- ADO.NET事务学习小结
- spring中事务的小结
- 事务型数据库设计小结
- 一个XA事务问题解决小结
- spring中事务的小结
- SQLSERVER-存储过程-事务-小结
- Android资源文件
- 修改桌面路径
- 编译错误syntax error : missing ';' before 'type'原因探寻(VS 编译C文件)
- Android动画效果translate、scale、alpha、rotate详解
- 程序员只能吃青春饭?接下来只有一条出路?
- 事务小结
- BNU 0817 B. Alice and Bob
- 一步步写驱动---cdev
- Xcode改成不用MainWindow.xib 和 RootViewController.xib 的方法
- RHEL6.3 安装PPTP VPN Client
- 编码20年的老程序员分享所积累的20条编程经验
- 代码托管
- openvpn 在centos5.5下的配置
- Extjs EditorGridPanel 动态追加一行