SqlDataAdapter.Update批量数据更新

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

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

SqlCommandBuiler方式:

 public static void AddInfo()
        {
            string str1 = "Server=.;user=sa;pwd=sa;database=One_db";
            SqlConnection conn = new SqlConnection(str1);
            conn.Open();
            SqlCommand cmd = new SqlCommand("select * from Info", conn);
            DataTable dt = new DataTable();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.Fill(dt);

            for (int i = 0; i < 4; i++)
            {
                dt.Rows.Add(new object[] { i + 4, "aa0" + i, "soft", "12345678945" });
                
            }
            
            SqlCommandBuilder scb = new SqlCommandBuilder(da);
            da.Update(dt.GetChanges());
            dt.AcceptChanges();
            outValueDT(dt);显示datatable信息
            conn.Close();
        }

 

 软件运行之前 数据库的数据为:

运行之后的数据为:

 

2、执行删除和修改命令

public static void DeleteInfo()
        {
            string str1 = "Server=.;user=sa;pwd=sa;database=One_db";
            SqlConnection conn = new SqlConnection(str1);
            conn.Open();
            SqlCommand cmd = new SqlCommand("select * from Info", conn);
            DataTable dt = new DataTable();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.Fill(dt);

            dt.Rows[0][1] = "wangyu";
            dt.Rows[1][3] = "13924658789";
       dt.Rows.RemoveAt(2); //dt.Rows[3].Delete(); SqlCommandBuilder scb = new SqlCommandBuilder(da); da.Update(dt.GetChanges()); dt.AcceptChanges(); outValueDT(dt); //显示datatable信息 conn.Close(); }

 如果没有设置主键  将会出现错误

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

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

使用dt.Rows.RemoveAt(2)  显示dt时,  发现 dt里面的索引值为2的行被删除,但是 数据库里面的相应行并没有被删除

想要删除数据库里面的 需要使用dt.Rows[2].Delete(); 

 

修改代码后   第0行第一列的数据  第1行第3列的数据 已经修改   ,索引值为2的row删除 数据库数据为:

 

注意:

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

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

所以使用SqlCommandBuilder时应该注意的2点:表要有主键,应使用delete方法删除行.SqlCommandBuilder用来自动生成添加、删除、修改的语句

 

在使用Update()这个函数前,我们得知道一点,那就是一个DataTable有个记录RowState的字段(不知称其为字段合适不合适),当我们对表进行过添加、修改、删除之后,这个RowState会记录我们的操作,而Update()方法正是根据RowState进行对数据库表的更新的。有点需要注意,那就是添加和删除操作:当我们使用Add()方法添加一个新行和Delete()方法删除一行的时候是没有问题的,DataTable都正确记录下来了我们的操作,并能在Update()函数下正确更新到数据库中,但是当我们使用Import()方法导入一行或Remove()删除一行的时候,我们此时再使用Update()方法,发现我们的添加和删除没有成功,这是为什么呢?我们分别来看一下:

Import()方法,我们导入的是一个已经存在于其他表里的行,而这个被导入的行的RowState记录的是什么是不确定的,所以导入到我们的DataTable中的时候,我们的DataTable并不一定把这一行当作是添加的行;

RemoveAt()方法,在我们使用RemoveAt()方法的时候,我们的DataTable并没有真正的把这一行删除了,而只是记录了一个删除状态,当我们使用DataTable的AcceptChanges()的时候,记录为删除状态的行才被真正删除了,而RemoveAt()方法是直接把行删除了,所以再使用Update()方法时没有实现对数据库对应表的行删除功能

    当我们完成了Update()函数之后应该调用DataTable()的AcceptChanges()方法,把DataTable的RowState记录初始化。用进行过RowState初始化(即调用过AcceptChanges ())的DataTable去Update()数据库中的表,将不会进行任何更新。

我在项目里用这个Update()方法的时候是这么用的:我并不是从数据库中先读出一张DataTable,进行一些添加或删除或修改,然后Update(),而是我有一张现成的dataTable,我最初的想法是想让我的这张DataTable和数据库中对应的表进行对比,然后根据两张表的不同之处进行更新,但实际上这是无法实现的,是我最初没有真正明白Update()函数的原理。所以,SqlDataAdapter的Update()方法不是拿数据库中的表和程序中的一个DataTable进行对比更新,而是根据程序中的DataTable中记录的RowState进行更新。

所以,我们想要使用这个Update()方法实现批量更新,必须让我们的DataTable正确记录所有的RowState,当更新完成后还应调用AcceptChanges()方法对DataTable的RowState进行初始化。

 

转载于:https://www.cnblogs.com/rosesmall/p/8568636.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值