zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    C语言冒泡排序例子 JIANG
    C语言技巧 JIANG
    ligerui 表格树中 Uncaught TypeError: p.tree.isParent is not a function 纵一苇之所如
    npoi 已删除的功能: /xl/styles.xml 部分的 格式 (样式) 纵一苇之所如
    超过了为 maxJsonLength 属性设置的值。 纵一苇之所如
    MySQL+Canal+RocketMQ+SpringBppt+ElasticSearch+Redis开源整合
    [开源项目发布]Observer:根据map文件测试程序在运行中各个函数的运行时间
    [工作环境搭建]笔记本与台式机共享鼠标与键盘
    探秘C++机制的实现
    自己实现函数钩子
  • 原文地址:https://www.cnblogs.com/Percy_Lee/p/5054555.html
Copyright © 2011-2022 走看看