• C#利用SqlDataAdapte对DataTable进行批量数据操作


      C#利用SqlDataAdapte对DataTable进行批量数据操作,可以让我们大大简化操作数据的代码量,我们几乎不需要循环和不关心用户到底是新增还是修改,更不用编写新增和修改以及删除的SQL语句,适配器都帮我们在后台进行了很好的处理.

      如果您要通过 SQL Server 存储过程使用 DataAdapter 来编辑或删除数据,请确保不要在存储过程定义中使用 SET NOCOUNT ON。这将使返回的受影响的行数为零,DataAdapter 会将其解释为并发冲突。在许多情况下,以何种顺序向数据源发送通过 DataSet 所做的更改是非常重要的。例如,如果更新了现有行的主键值,并且添加了以新主键值作为外键的新行,则务必要在处理插入之前处理更新。可以使用 DataTable 的 Select 方法来返回仅引用具有特定 RowState 的 DataRow 数组。然后可以将返回的 DataRow 数组传递给 DataAdapter 的 Update 方法来处理已修改的行。通过指定要更新的行的子集,可以控制处理插入、更新和删除的顺序。以下代码确保首先处理表中已删除的行,然后处理已更新的行,然后处理已插入的行。

    1 DataTable table = dataSet.Tables["Customers"];
    2 //第一步处理删除.
    3 adapter.Update(table.Select(null, null, DataViewRowState.Deleted));
    4 //接着处理更新
    5 adapter.Update(table.Select(null, null, 
    6   DataViewRowState.ModifiedCurrent));
    7 //最后处理新增
    8 adapter.Update(table.Select(null, null, DataViewRowState.Added));

     注意   对 DataSet、DataTable 或 DataRow 调用 AcceptChanges 将导致 DataRow 的所有 Original 值被 DataRow 的 Current 值覆盖。如果修改了唯一标识该行的字段值,则在调用 AcceptChanges 后,Original 值将不再匹配数据源中的值。在调用 DataAdapter 的 Update 方法期间会对每一行自动调用 AcceptChanges。在调用 Update 方法期间,通过先将 DataAdapter 的 AcceptChangesDuringUpdate 属性设置为 false,或为 RowUpdated 事件创建一个事件处理程序并将 Status 设置为 SkipCurrentRow,可以保留原始值。(来自MSDN) 

    1 强类型数据集

      数据库的表设计好后,可以用VS连接数据库,并将myUser 表拖放到数据集设计器中(重命名为dsUser),默认情况下,数据集会自动生成Fill方法,我们这里需要手动进行删除,只保留表结构即可,数据查询和操作逻辑我们进行自定义.如下图所示:

    2 UI设计

      新建一个窗体,编译后可以从工具栏将上一步新建的dsUser强类型数据集拖放到窗体上,另外添加一个BindingSource控件(主要用于对DataGridView中的数据库和DataSet的数据进行绑定)

      BindingSource中选择数据源DataSource为dsUser,然后选择数据集中的一个表myUser进行绑定:

      设置DataGridView的数据源为bindingSource,这样通过bindingSource1就实现了DataGridView和dsUser的数据绑定,也就是说在界面DataGridView上进行操作,可以同步到dsUser中(会在每行上打上标志)

     3 数据操作方法

      可以利用SqlDataAdapter批量更新DataTable中的数据库,也支持表格中同时进行了删除/修改和新增的操作,下面的代码中,用select * from {0} where 1=2查询语句为SqlDataAdapter提供架构:

     //生成架构
    string selectSQL = string.Format("select * from {0} where 1=2", dt.TableName);
    SqlDataAdapter sda = new SqlDataAdapter(selectSQL, ConnectionString)

     而后用SqlCommandBuilder自动构建新增/删除/修改的命令,这样就可以用sda.Update()方法对数据表进行批量操作了:

    1 SqlCommandBuilder scb  =  new SqlCommandBuilder(sda);
    2 sda.Update(dt);

     完整代码如下:

     1 public static void UpdateDataSet(DataSet ds, string tableName)
     2 {
     3     try
     4     {
     5         if (tableName == "")
     6         {
     7             throw new ArgumentNullException("tableName 不能为空");
     8         }
     9         //生成架构
    10         string selectSQL = string.Format("select * from {0} where 1=2", tableName);
    11         using (SqlDataAdapter sda = new SqlDataAdapter(selectSQL, ConnectionString))
    12         {
    13 
    14             SqlCommandBuilder scb = new SqlCommandBuilder(sda);
    15 
    16             sda.UpdateCommand = scb.GetUpdateCommand();
    17             sda.InsertCommand = scb.GetInsertCommand();
    18             sda.DeleteCommand = scb.GetDeleteCommand();
    19 
    20             sda.Update(ds, tableName);
    21             ds.Tables[tableName].AcceptChanges();
    22             DisposeCommand(sda.UpdateCommand);
    23             DisposeCommand(sda.InsertCommand);
    24             DisposeCommand(sda.DeleteCommand);
    25             sda.Dispose();
    26             scb.Dispose();
    27         }
    28     }
    29     catch (SqlException e)
    30     {
    31         throw e;
    32     }
    33 }
    View Code

      为了确保在用户编辑完成后,立刻将数据同步到数据集中,必须调用bindingSource的EndEdit方法来同步数据.

    1 private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    2 {
    3    this.bindingSource.EndEdit();
    4 }

       在窗体加载时,调用刷新方法,然后程序会自动将数据绑定到DataGridView上:

    1 private bool fnRefresh()
    2 {
    3     string sql = string.Format("select * from myUser");
    4     CM.Products.DataAccess.SqlHelper.GetDataTableBySQL(this.dsUser.myUser, sql);
    5     return true;
    6 }

       我们可以通过DataGridView的EndEdit方法来获取当前用户是否已经结束编辑:

    1 bool isEnd= this.dataGridView1.EndEdit();

       另外可以通过GetChanges()方法来获取修改的数据,返回一个DataTable.

    1 DataTable dtModify = this.dsUser.myUser.GetChanges(DataRowState.Modified);

      调用UpdateTable方法,即可对表格进行批量处理(这里就一个表,如果是多个表,那么需要指明表名):

     1 private bool Save()
     2 {
     3     try
     4     {
     5         DataAccess.SqlHelper.UpdateDataSet(this.dsUser, "myUser");
     6         this.dsUser.myUser.AcceptChanges();//提交数据库
     7         return true;
     8     }
     9     catch (Exception ex)
    10     {
    11         return false;
    12     }
    13 
    14 }

      当用户选择一个单元格时,会获取到当前行的索引,然后调用RemoveAt()方法进行删除,由于用bindingSource进行了绑定,可以直接调用save()方法进行数据保存:

     1 private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
     2 {
     3     if (this.dataGridView1.CurrentRow != null)
     4     {
     5         int index = this.dataGridView1.CurrentRow.Index;
     6         if (index > -1)
     7         {
     8             this.dataGridView1.Rows.RemoveAt(index);
     9             Save();
    10         }
    11     }
    12 }

      当用户单击新增按钮时,我们创建一个强类型的myUserRow,然后给它附上默认值(特别是主键)

     1 //add row
     2 private void toolStripButton1_Click(object sender, EventArgs e)
     3 {
     4     Common.dsUser.myUserRow dr = this.dsUser.myUser.NewmyUserRow();
     5     dr["ID"] = System.Guid.NewGuid().ToString();
     6     dr["Name"] = "Name";
     7     dr["AddTime"] = DateTime.Now.ToString();
     8 
     9     this.dsUser.myUser.AddmyUserRow(dr);
    10 }
  • 相关阅读:
    软件测试之功能测试简单介绍
    如果编程语言是女孩,你猜C语言是萝莉还是御姐?
    C++ C、C++、C#、VC、VC.net以及VC++有什么区别和联系?
    程序员如何避免陷入内卷?从以下三个方面着手
    懒惰使人进步,UNIX 和 Linux 新系统的诞生只是意外
    编程学习必备:C++ 学习的 11 本经典书籍推荐
    初入职场,菜鸟程序员如何才能成为业界大牛,给你提供思路方法。
    TIOBE 12月编程语言: Python、Java战况激烈, C语言:我自岿然不动
    C++基础知识篇:C++ 数字
    二本毕业程序员鄙视清北毕业生,嘲笑水货一抓一大把,你怎么看?
  • 原文地址:https://www.cnblogs.com/isaboy/p/csharp_ADO_NET_DataTable_dataset_adapter_SQL.html
Copyright © 2020-2023  润新知