相关知识:
- DataSet中的数据一旦从数据库下载下来,便不再与数据库保持联系。如果修改了DataSet中的数据,需要重新建立连接,并且通过SQL命令将修改更新到数据库去
- 编写SQL命令往往比较繁琐和机械化,ADO.NET提供了一个SqlCommandBuilder对象,帮助DataAdapter对象从SELECT语句推算出需要的UPDATE,DELETE和INSERT语句;然后DataAdapter便可以利用这些语句,检查DataSet中被修改的数据,然后提交到数据库
- SqlCommandBuilder自动生成的SQL命令虽然方便,但却不灵活。尤其是在需要向多个表中写入数据的时候,往往需要自定义增删改语句
代码示例:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Data; 7 using System.Data.SqlClient; 8 9 namespace ConsoleApplication11 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 string strConn = @"server=Joe-PC;database=AccountDBforSQLInjection;uid=sa;pwd=root"; 16 SqlConnection conn = new SqlConnection(strConn); 17 18 string sql = "SELECT AccountID,AccountName,password FROM Account"; 19 SqlDataAdapter da = new SqlDataAdapter(sql, conn); 20 21 DataSet ds = new DataSet(); 22 23 da.Fill(ds, "Account"); 24 25 Console.WriteLine("Account表中原有数据:"); 26 27 DataTable dt = ds.Tables["Account"]; 28 DataView dv = new DataView(dt); 29 dv.Sort = "AccountID ASC"; 30 31 foreach (DataRowView drv in dv) 32 { 33 Console.WriteLine("{0}:{1},{2}", drv[0], drv[1], drv[2]); 34 } 35 36 Console.WriteLine(""); 37 38 //添加一行数据——Insert 39 DataRow newRow = dt.NewRow(); //根据Table的架构,创建一个新的空行 40 // 给新行赋值 41 newRow["AccountID"] = 4; 42 newRow["AccountName"] = "new"; 43 newRow["password"] = "123456"; 44 // 将新行加到表的行集合中 45 dt.Rows.Add(newRow); 46 47 //修改一行数据——Update 48 DataRow updateRow = dt.Rows[0]; //修改表中第一行数据 49 updateRow["password"] = "000000";//修改了密码为000000 50 51 //删除一行数据——Delete 52 DataRow deleteRow = dt.Rows[1];//准备删除原表中第二行数据 53 dt.Rows.Remove(deleteRow); 54 55 //测试内存中数据 56 Console.WriteLine("修改后,Account表中现有数据"); 57 foreach (DataRowView drv in dv) 58 { 59 Console.WriteLine("{0}:{1},{2}", drv[0], drv[1], drv[2]); 60 } 61 62 //程序在此暂停等待用户输入,检查数据库,newRow此时尚未插入到数据库中。 63 //此时newRow仅仅是在DataSet对象内存中创建,并为更新到数据库 64 Console.WriteLine(""); 65 Console.WriteLine("检查数据库中是否已经创建了新行,然后按回车继续。"); 66 Console.ReadLine(); 67 68 //更新到数据库 69 //创建SqlCommandBuilder,并且把DataAdapter对象传入。 70 SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da); 71 Console.WriteLine("生成的Insert语句:{0}", cmdBuilder.GetInsertCommand().CommandText); 72 Console.WriteLine("生成的Update语句:{0}", cmdBuilder.GetUpdateCommand().CommandText); 73 //之前建DataAdapter时候的sql语句,SELECT的键列,必须含有主键,此处SqlCommandBuilder的update才能成功 74 Console.WriteLine("生成的Delete语句:{0}", cmdBuilder.GetDeleteCommand().CommandText); 75 //执行更新 76 da.Update(dt);//将table中的所有修改更新到数据库 77 Console.WriteLine("数据更新到数据库。检查数据库中是否已经更新了数据。"); 78 79 Console.WriteLine(""); 80 81 //重新输出数据库中数据,检测以上操作是否成功 82 string _sql = "SELECT AccountID,AccountName,password FROM Account"; 83 SqlDataAdapter _da = new SqlDataAdapter(_sql, conn); 84 _da.Fill(ds, "newAccount"); 85 Console.WriteLine("Account表中现有数据:"); 86 87 DataTable _dt = ds.Tables["newAccount"]; 88 DataView _dv = new DataView(_dt); 89 _dv.Sort = "AccountID ASC"; 90 91 foreach (DataRowView drv in _dv) 92 { 93 Console.WriteLine("{0}:{1},{2}", drv[0], drv[1], drv[2]); 94 } 95 96 Console.WriteLine(""); 97 } 98 } 99 }
程序分析:
- 在DataSet中修改数据,仅是改了程序内存中的数据,并不会影响到数据库
- 通过SqlCommandBuilder帮助构建增删改的SQL语句。通过打印这些语句命令,可以看出,它们是用过参数来执行SQL命令的。当正式更新数据时,会用DataSet中的修改后的数据来填充这些参数值
- 调用SqlDataAdapter对象的Update方法,正式将数据更新到数据库
扩展问题:
如果在Fill一个DataSet时的SQL语句是同时从多个表中联合查询的数据,那么要更新数据时,插删改的语句将如何生成呢?