在进行机房收费系统时,有个学生注册这么一个功能。注册功能需要向Student(学生)表、Card(卡)表、ChargeRecord(充值记录)表写入记录。
当时,在处理这个问题时,存在一个困惑,如果在向数据库插入数据时,Student表插入成功,Card表或ChargeRecord表未能插入成功怎么办?这样不就导致了数据不一致吗?
后来通过查笔记,发现在ADO.Net中,有“事务”这么一致处理机制。事务有原子性、一致性、隔离性、持久性4种特征,通过“事务”这种处理机制,可以保证数据的一致性。
在ADO.Net中,又分为“本地事务处理”和“分布式事务处理”。“本地事务处理”操作是一个数据库,“分布式事务处理”操作的是多个数据库,这是它们的区别。
因为这次只用到了一个数据库,那我们就先从“本地事务处理”开始学习。
下面让我用一个小Demo来向大家讲解:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient; namespace TransactionDemo { class Program { static void Main(string[] args) { //声明一个字符串型的数组 string[] categoryName = new string[] { "aaa", "bbb", "ccc", "ddd", "eee" }; //连接数据库的字符串 string strCon = "Data Source=.;Initial Catalog=test;uid=sa;pwd=123456;"; using (SqlConnection con = new SqlConnection(strCon)) { using (SqlCommand cmd = con.CreateCommand()) { con.Open(); //创建一个事务 SqlTransaction trans = con.BeginTransaction(); cmd.Transaction = trans; try { //将数组中的数据分别插入到数据表B中的bID字段 for (int i = 0; i < categoryName.Length; i++) { string ins = "insert into B(bID) values('" + categoryName[i] + "')"; cmd.CommandText = ins; cmd.ExecuteNonQuery(); } //提交事务 trans.Commit(); } catch (Exception ex) { Console.WriteLine(ex.Message); //如果事务未完成,则回滚到初始状态 trans.Rollback(); } } } } } }
如果全部执行成功,则数组中的数据会插入到数据库;如果数组中的任何一条数据未能执行成功,则全部插入失败,回滚到初始状态。
在这里SqlConnection相当于一条铁路线,SqlTransaction相当于铁路线上的一列火车,SqlCommand相当于火车上的一列车厢。所以当有多个SqlCommand(车厢)时,需要把多个SqlCommand指定到同一个SqlTransaction上(告诉这个车厢,它属于哪列火车),再把这个SqlTransaction指定到同一个SqlConnection上,事务才能正常执行。执行过程好比SqlTransaction这列火车,要么全部车厢到达,要么一列车厢都不能到达。
这个情景告诉我们平时要多思考沉淀,多阅读别人的博客。通过思考我们可以发现别人没有注意到的问题,通过阅读我们可以学习到很多经典问题的解决方案。让我们都站在巨人的肩膀上,不必在苦苦思索了很久后才发现原来此类问题早已有解决方案的囧境。
希望我的讲解能对大家有所帮助。