SqlDataAdapter.Update批量数据更新

SqlDataAdapter.Update批量数据更新

使用SqlDataAdapter.Update可以方便地对数据库进行快速、批量数据更新。我们最常用的多条数据更新方法是使用循环多次执行SQL语句或存储过程,这样虽然方便,但由于连接和数据传递要在服务器和客户端多次来往,大大增加了整个过程的时间,当数据越大时越明显!

下面对SqlDataAdapter.Update作个简单的演示介绍吧。

测试环境:SqlServer2008+VS2010+WinXP

1.建立测试数据库和表

CREATE DATABASE [TEST] GO
USE [Test] GO
CREATE TABLE [Student](     [SNo] [int] NOT NULL,     [SName] [nvarchar](50) ,     [SAge] [int] ) O GO

2.建立解决方案和项目

使用SqlDataAdapter.Update更新有三种方式,即SqlCommandBuiler自动生成更新,使用配置数据源方式更新,手动编写命令。

 

SqlCommandBuiler方式:

代码1:

private void Form1_Load(object sender, EventArgs e)         {             string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";             SqlConnection conn = new SqlConnection(constr);             //设置select查询命令,SqlCommandBuilder要求至少有select命令             SqlCommand selectCMD = new SqlCommand("select top 0 SNo,SName,SAge from Student", conn);             DataTable dt = new DataTable();             SqlDataAdapter sda = new SqlDataAdapter(selectCMD);             //上面的语句中使用select 0,不是为了查询出数据,而是要查询出表结构以向DataTable中填充表结构             sda.Fill(dt);             //给DataTable添加10条记录             for(int i=1;i<=10;i++)             dt.Rows.Add(new object[] { i, "aaa"+i, 20+i });             SqlCommandBuilder scb = new SqlCommandBuilder(sda);             //执行更新             sda.Update(dt.GetChanges());             //使DataTable保存更新             dt.AcceptChanges();                     }

 

//执行后查看表中数据,如图:

上面我只作了插入操作,那现在将Select中的Top 0 去掉,把表中的数据全部加载到DataTable然后执行删除和更新操作

代码2

  private void Form1_Load(object sender, EventArgs e)         {

    string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";             SqlConnection conn = new SqlConnection(constr);             //设置select查询命令,SqlCommandBuilder要求至少有select命令             SqlCommand selectCMD = new SqlCommand("select  SNo,SName,SAge from Student", conn);             DataTable dt = new DataTable();             SqlDataAdapter sda = new SqlDataAdapter(selectCMD);             //上面的语句中使用select 0,不是为了查询出数据,而是要查询出表结构以向DataTable中填充表结构             sda.Fill(dt);             //先更新第1,2条数据的SName和SAge             dt.Rows[0]["SName"] = "AAA";             dt.Rows[0]["SAge"] = 33;             dt.Rows[1]["SName"] = "BBB";             dt.Rows[1]["SAge"] = 444;             //然后使用RemoveAt删除第3,4条数据             dt.Rows.RemoveAt(2);             dt.Rows.RemoveAt(3);             //使用Delete删除             //dt.Rows[2].Delete();             //dt.Rows[3].Delete();             SqlCommandBuilder scb = new SqlCommandBuilder(sda);             //执行更新             sda.Update(dt.GetChanges());             //使DataTable保存更新             dt.AcceptChanges();

}

执行后将出错,错误信息“对于不返回任何键列信息的 SelectCommand,不支持 UpdateCommand 的动态 SQL 生成。”

出错原因是建表时没有设置主键。主键唯一标识一行数据,SqlCommandBuilder是根据DataTable每行的RowState及对应的主键来生成命令的,没有主键就无法确定删除哪条数据,当然不可能根据其他列来删除,因为其他列可能重复,这样会删除多行数据,很可能执行后不是你想要的结果,这种不确定性的对数据的操作方法,微软当然不可能提供给你!

那就给表添加主键吧

执行如下SQL语句: alter table student add constraint PK_Student primary key(SNo)

再次执行上面的代码2.

执行后

我们发现第1,2行数据更新了,但是第3,4行却没有删除。这是怎么回事呢?

先不急,把代码2中的

dt.Rows.RemoveAt(2);   dt.Rows.RemoveAt(3);

注释掉,同时把

//dt.Rows[2].Delete();    //dt.Rows[3].Delete();

的注释去掉,使之执行Delete方法而不是RemoveAt方法

再看看结果:

第3,4行已经删除。

原因是:使用RemoveAt或Remove会将数据真正的从DataTable中删除,而使用Delete则不会,而仅是把当前行的RowState值置为deleted.

前面说过SqlCommandBuilder是根据RowState和主键来生成命令的,RemoveAt/Remove把数据删除了,怎么能找到主键和RowState呢?

所以使用SqlCommandBuilder时应该注意的2点:表要有主键,应使用delete方法删除行.

手写命令方法:

代码3:

  private void Form1_Load(object sender, EventArgs e)         {             string constr = "server=localhost\\sqlserver2008;initial catalog=test;uid=sa;pwd=123456;";             SqlConnection conn = new SqlConnection(constr);             //设置select查询命令             SqlCommand selectCMD = new SqlCommand("select  SNo,SName,SAge from Student", conn);             //Insert命令             SqlCommand insertCMD = new SqlCommand("insert into Student(SNo,SName,SAge) values(@SNo,@SName,@SAge)", conn);             //Update命令             SqlCommand updateCMD = new SqlCommand("update Student Set SName=@SName,SAge=@SAge where SNo=@SNo", conn);             //Delete命令             SqlCommand deleteCMD = new SqlCommand("delete from Student where SNo=@SNo", conn);
            //给Insert,Update,Delete三个命令添加参数             SqlParameter paraSNo1, paraSNo2, paraSNo3;//第二个指定参数值的来源,这里的SNo是指DataTable中的列名             paraSNo1 = new SqlParameter("@SNo", "SNo");             paraSNo2 = new SqlParameter("@SNo", "SNo");             paraSNo3 = new SqlParameter("@SNo", "SNo");             paraSNo1.SourceVersion = DataRowVersion.Current;//指定SourceVersion确定参数值是列的当前值(Current),还是原始值(Original),还是建议值(Proposed)             paraSNo2.SourceVersion = DataRowVersion.Current;             paraSNo3.SourceVersion = DataRowVersion.Current;
            SqlParameter paraSName1, paraSName2, paraSName3;             paraSName1 =  new SqlParameter("@SName", "SName");             paraSName2 = new SqlParameter("@SName", "SName");             paraSName3 = new SqlParameter("@SName", "SName");             paraSName1.SourceVersion = DataRowVersion.Current;             paraSName2.SourceVersion = DataRowVersion.Current;             paraSName3.SourceVersion = DataRowVersion.Current;
            SqlParameter paraSAge1, paraSAge2, paraSAge3;             paraSAge1 = new SqlParameter("@SAge", "SAge");             paraSAge2 = new SqlParameter("@SAge", "SAge");             paraSAge3 = new SqlParameter("@SAge", "SAge");             paraSAge1.SourceVersion = DataRowVersion.Current;             paraSAge2.SourceVersion = DataRowVersion.Current;             paraSAge3.SourceVersion = DataRowVersion.Current;
            insertCMD.Parameters.AddRange(new SqlParameter[] { paraSNo1, paraSName1, paraSAge1 });             updateCMD.Parameters.AddRange(new SqlParameter[] { paraSNo2, paraSName2, paraSAge2 });             deleteCMD.Parameters.AddRange(new SqlParameter[] { paraSNo3, paraSName3, paraSAge3 });
            DataTable dt = new DataTable();             SqlDataAdapter sda = new SqlDataAdapter(selectCMD);             sda.Fill(dt);             //插入2条数据             dt.Rows.Add(new object[] { 11, "aa11", 31 });             dt.Rows.Add(new object[] { 12, "aa12", 32 });

            //先更新第1,2条数据的SName和SAge             dt.Rows[0]["SName"] = "CCC";             dt.Rows[0]["SAge"] = 55;             dt.Rows[1]["SName"] = "DDD";             dt.Rows[1]["SAge"] = 66;
            //使用Delete删除第3,4条数据             dt.Rows[2].Delete();             dt.Rows[3].Delete();             SqlCommandBuilder scb = new SqlCommandBuilder(sda);             //执行更新             sda.Update(dt.GetChanges());             //使DataTable保存更新             dt.AcceptChanges();         }

执行结果:

可以看到

第SNo为11,12的数据是新增的。

原来SNo为1,2的数据中SName已经从AA,BB更改为CC,DD,另一列SAge从33,44更改为55,66。

原来SNo为5,6也就是第3,4条数据已经被删除

出处:http://www.cnblogs.com/moss_tan_jun/archive/2011/11/26/2263992.html

posted on 2013-10-31 09:40  Q&A  阅读(116)  评论(0)    收藏  举报