博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转载]C#中使用ADO.NET连接SQL Server数据库,自动增长字段用作主键,处理事务时的基本方法...
阅读量:5743 次
发布时间:2019-06-18

本文共 8063 字,大约阅读时间需要 26 分钟。

问题描述:

假设在数据库中存在以下两张数据表:

User表,存放用户的基本信息,基本结构如下所示:

  类型 说明
ID_User int 自动增长字段,用作该表的主键
UserName varchar  

 

 

 

 

UserDepart表,存放用户所拥有的部门(我们假设一个用户拥有多个部门,虽然听起来有点别扭,此处仅作示例,可以理解为一个用户拥有多个职位等等),该表的基本结构如下所示:

  类型 说明
ID_UserDepart int 自动增长字段,用作该表的主键
ID_User int 用户编号
ID_Depart int 部门编号

 

 

 

 

 

向数据库中插入一条用户信息的时候,为了保证数据的一致性,必须使用事务的方式“同时”操作User表和UserDepart表。先将用户姓名写入User表中,再将其所拥有的部门写入UserDepart表中,使用事务机制保证这两步操作要么同时成功,要么同时失败。问题就出在:第一步操作完成后,我们并不知道该向第二步操作写入的ID_User的值是多少,因为这个值是SQL Server自动生成的。

 

解决思路:

可以借助 SELECT IDENT_CURRENT('User') AS ‘NewInsertID’ 来查询最近一次插入User表的数据的自动编号的值。

 

程序实现:

1 public struct Chaos_TranSQLCmd 2         { 3             ///  4             /// 一条SQL语句 5             ///  6             public string strSQL; 7  8             ///  9             /// 标记该条SQL语句是否需要连接ID_User10             /// 11             public bool bNeedID;12         }13 14 15         public void Chaos_ExecuteSqlTran(List
listTranSQLCmd,string strInsertID_SQL)16 {17 using (SqlConnection ChaosSqlConn = new SqlConnection(strSqlConnString))18 {19 SqlCommand ChaosSqlCmd = new SqlCommand();20 ChaosSqlCmd.Connection = ChaosSqlConn;21 ChaosSqlConn.Open();22 SqlTransaction ChaosSqlTran = ChaosSqlConn.BeginTransaction();23 ChaosSqlCmd.Transaction = ChaosSqlTran;24 25 try26 {27 string mID_User = "";28 29 //先将数据插入User30 ChaosSqlCmd.CommandText = strInsertID_SQL;31 ChaosSqlCmd.ExecuteNonQuery();32 33 //再获取ID_User34 DataSet ds = this.ExecAdapter("select IDENT_CURRENT('PT_User') as 'ID'", "T");35 DataTable dt = ds.Tables["T"];36 if (dt.Rows.Count>0)37 {38 mID_User = dt.Rows[0]["ID"].ToString(); 39 }40 41 for (int i = 0; i < listTranSQLCmd.Count; i++)42 {43 //如果队列中的语句需要连接ID,则处理SQL语句后再执行44 string strSQL = "";45 if (listTranSQLCmd[i].bNeedID==true)46 {47 strSQL = string.Format(listTranSQLCmd[i].strSQL, mID_User);48 }49 else50 {51 strSQL = listTranSQLCmd[i].strSQL;52 }53 54 ChaosSqlCmd.CommandText = strSQL;55 ChaosSqlCmd.ExecuteNonQuery();56 }57 58 //全部成功执行则提交59 ChaosSqlTran.Commit();60 }61 catch (System.Data.SqlClient.SqlException Ex)62 {63 //发生问题则回滚64 ChaosSqlTran.Rollback();65 throw new Exception(Ex.Message);66 }67 }68 }

 

测试代码如下:

1 static void Main(string[] args) 2         { 3             try 4             { 5                 List
Chaos_SQLCmdList = new List
(); 6 7 //构造SQL语句向User表中写入数据 8 string strSQL = "insert into PT_User (UserName) values ('Lee')"; 9 10 //构造SQL语句向UserDepart表写入数据11 for (int i = 0; i < 10; i++)12 {13 DB_Operation.ChaosDbOprt.Chaos_TranSQLCmd nCmd = new DB_Operation.ChaosDbOprt.Chaos_TranSQLCmd();14 if (i==6)15 {16 //构造错误SQL语句,使写入数据库的操作不能成功执行17 nCmd.strSQL = "insert into PT_UserDepart (ID_User,ID_Depart) values ({0}," + "A String which can't be inserted as ID_Depart)";18 }19 else20 {21 //正常SQL语句22 nCmd.strSQL = "insert into PT_UserDepart (ID_User,ID_Depart) values ({0}," + i.ToString() + ")";23 }24 nCmd.bNeedID = true;25 Chaos_SQLCmdList.Add(nCmd);26 }27 28 DB_Operation.ChaosDbOprt CDO = new DB_Operation.ChaosDbOprt();29 CDO.Chaos_ExecuteSqlTran(Chaos_SQLCmdList, strSQL);30 31 Console.WriteLine("数据写入成功!");32 Console.ReadLine();33 }34 catch (Exception ex)35 {36 Console.WriteLine("Error:\r\n"+ex.Message);37 Console.ReadLine();38 } 39 }

 

 

规范化代码如下:

 

1 #region 实现数据库事务的方法,实现以事务的方式将多条SQL语句同时写入数据库(其中某些语句依赖于第一条语句插入数据库后自动生成的ID) 2  3         public struct Chaos_TranSQLCmd 4         { 5             ///  6             /// 一条SQL语句,在需要添加ID的地方用"{0}"来代替 7             /// 如:INSERT INTO PT_FeeItemDetails(ID_FeeItem,ID_ExamItem) VALUES ({0},005)等 8             ///  9             public string strSQL;10 11             /// 12             /// 标记该条SQL语句是否需要连接ID13             /// 14             public bool bNeedID;15         }16         /// 17         /// 该函数用于实现以事务的方式将多条SQL语句同时写入数据库(其中某些语句依赖于第一条语句插入数据库后自动生成的ID)18         /// 19         /// 需要先插入数据库中以产生ID的SQL语句20         /// 需要首先插入数据库中以产生ID的数据表的名称,如"PT_FeeItem"等21         /// 需要连接ID的SQL语句的列表  22         public void Chaos_ExecuteSqlTran_InsertID(string strInsertID_SQL,string strTableName, List
listTranSQLCmd)23 {24 using (SqlConnection ChaosSqlConn = new SqlConnection(strSqlConnString))25 {26 SqlCommand ChaosSqlCmd = new SqlCommand();27 ChaosSqlCmd.Connection = ChaosSqlConn;28 ChaosSqlConn.Open();29 SqlTransaction ChaosSqlTran = ChaosSqlConn.BeginTransaction();30 ChaosSqlCmd.Transaction = ChaosSqlTran;31 32 try33 {34 string m_strID = "";35 36 //先将数据插入User37 ChaosSqlCmd.CommandText = strInsertID_SQL;38 ChaosSqlCmd.ExecuteNonQuery();39 40 string strSQL_Tmp = string.Format("SELECT IDENT_CURRENT('{0}') as 'ID'",strTableName);41 //再获取ID42 DataSet ds = this.ExecAdapter(strSQL_Tmp, "T");43 DataTable dt = ds.Tables["T"];44 if (dt.Rows.Count>0)45 {46 m_strID = dt.Rows[0]["ID"].ToString();47 48 for (int i = 0; i < listTranSQLCmd.Count; i++)49 {50 //如果队列中的语句需要连接ID,则处理SQL语句后再执行51 string strSQL = "";52 if (listTranSQLCmd[i].bNeedID == true)53 {54 strSQL = string.Format(listTranSQLCmd[i].strSQL, m_strID);55 }56 else57 {58 strSQL = listTranSQLCmd[i].strSQL;59 }60 61 ChaosSqlCmd.CommandText = strSQL;62 ChaosSqlCmd.ExecuteNonQuery();63 }64 }65 else66 {67 //如果没有正确获取首先插入语句的ID,则回滚68 ChaosSqlTran.Rollback();69 throw new Exception("产生ID语句没有成功执行,后续语句无法继续执行,已回滚!\r\n");70 } 71 72 73 //全部成功执行则提交74 ChaosSqlTran.Commit();75 }76 catch (System.Data.SqlClient.SqlException Ex)77 {78 //发生问题则回滚79 ChaosSqlTran.Rollback();80 throw new Exception(Ex.Message);81 }82 }83 }84 #endregion

转载于:https://www.cnblogs.com/joeymary/p/4758805.html

你可能感兴趣的文章
18 已知下面的字符串是通过RANDOM随机数变量md5sum|cut-c 1-8截取后的结果
查看>>
BZOJ - 3578: GTY的人类基因组计划2
查看>>
爱——无题
查看>>
分布式服务框架原来与实践 读书笔记一
查看>>
【http】post和get请求的区别
查看>>
TFS强制撤销某个工作区的文件签出记录
查看>>
EL表达式无法显示Model中的数据
查看>>
ps6-工具的基础使用
查看>>
linux下使用过的命令总结(未整理完)
查看>>
时间助理 时之助
查看>>
英国征召前黑客组建“网络兵团”
查看>>
PHP 命令行模式实战之cli+mysql 模拟队列批量发送邮件(在Linux环境下PHP 异步执行脚本发送事件通知消息实际案例)...
查看>>
pyjamas build AJAX apps in Python (like Google did for Java)
查看>>
centos5.9使用RPM包搭建lamp平台
查看>>
Javascript String类的属性及方法
查看>>
[LeetCode] Merge Intervals
查看>>
Struts2 学习小结
查看>>
测试工具综合
查看>>
【记录】JS toUpperCase toLowerCase 大写字母/小写字母转换
查看>>
在 Linux 系统中安装Load Generator ,并在windows 调用
查看>>