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条数据已经被删除

转载于:https://www.cnblogs.com/andylaufzf/archive/2011/11/10/2244499.html

SqlDataAdapter.Update批量数据更新相关推荐

  1. 用SqlDataAdapter.Update(DataSet Ds)更新数据库

    一. 用SqlDataAdapter.Update(DataSet Ds)更新数据库. 1. DbDataAdapter调用 Update 方法时,DataAdapter 将分析已作出的更改并执行相应 ...

  2. update 批量修改数据

    update 批量修改数据 更新同一张的数据表,将父ID赋值为对应的ID(根据父编码等于部门编码) update dept2 set parentdeptId=dept1.ID from BO_BY_ ...

  3. mysql update批量更新_MySql中4种批量更新的方法

    mysql 批量更新共有以下四种办法 1..replace into 批量更新 replace into test_tbl (id,dr) values (1,'2'),(2,'3'),...(x,' ...

  4. C# SqlDataAdapter.update结合事务(SqlTransaction)批量更新数据

    //此处的程序功能主要是将一个库中的表数据(源表)更新到另外一个库中的表数据(目标表) //实现目标表的数据和源表数据一致,已包括增加,更新和删除数据记录功能 //主调用代码块 SqlConnecti ...

  5. MySql数据库Update批量更新与批量更新多条记录的不同值实现方法

    批量更新 mysql更新语句很简单,更新一条数据的某个字段,一般这样写: UPDATE mytable SET myfield = 'value' WHERE other_field = 'other ...

  6. mysql update 批量更新_mysql 批量更新的两种方法

    本文介绍两种批量更新数据方法 数据准备 create table account ( id int auto_increment primary key, balance int not null ) ...

  7. mysql update 批量修改数据_MySQL 中实现数据的批量修改

    今天遇到一个数据的批量更新,查了一下官方文档,还好找到了.英文东东,大家耐心哈 http://dev.mysql.com/doc/refman/5.7/en/update.html 一般在使用数据编辑 ...

  8. mongo update批量更新

    参考链接  https://docs.mongodb.com/manual/reference/method/db.collection.update/ findAndModify只会更新一个, up ...

  9. python setdefault函数_python中字典中的赋值技巧,update批量更新、比较setdefault方法与等于赋值...

    知识回顾: 之前这节主要学习了字典的删除,主要涉及到两个方法: 1. Pop方法:删除指定的键的键值对.需要指定一个自己已知的键,删除后返回的是键对应的值. 2. Popitem方法:删除的是最后一个 ...

最新文章

  1. Android Studio 在项目中引用第三方jar包
  2. 用python解“BCD解密”问题
  3. JDK源码解析 Comparator 中的策略模式
  4. 临床观察性研究论文如何撰写“方法”?
  5. TiDB 分布式数据库(一)
  6. php sqlite id自增,Android sqlite设置主键自增长的方法教程
  7. 6*6行列式相加的c语言,求行列式的值,用C语言怎么写啊?
  8. ceph rbd 常用命令使用
  9. 如何画ROC曲线和FROC曲线
  10. 七牛云删除图片接口_Thinkphp连接七牛云存储空间删除图片
  11. django 1.11.16之环境搭建
  12. python数据框添加一列无列名_Pandas只使用列名创建空数据框
  13. 人脸识别活体检测技术讨论:基于背景人脸相对运动的活体判断方法
  14. javaweb实现在线支付功能
  15. 公有云、私有云、混合云
  16. Spyder窗口布局调整
  17. 三大框架之---MyBaits第二章
  18. 这15个PDF转化工具
  19. 信息爆炸的年代,怎么治愈自己的焦虑
  20. 国际宏观变化20221204

热门文章

  1. 记录之Learning Deep Features for Discriminative Localization阅读
  2. 寻找峰值(局部最大、局部最小)——二分查找
  3. [BUUCTF-pwn]——ciscn_2019_sw_1
  4. jsp java语法_javaweb-jsp语法
  5. Eclipse 安装Gradle插件
  6. JAVA学习:maven开发环境快速搭建How to download J2EE API (javaee.jar) from Maven
  7. 关闭钩子(ShutdownHook)
  8. spring viewResolver 类别
  9. 微信小程序 子组件调用父组件方法
  10. 美女同事DL-624+A家庭办公无线路由的解决方案!