C#利用SqlDataAdapte对DataTable进行批量数据操作
C#利用SqlDataAdapte对DataTable进行批量数据操作,可以让我们大大简化操作数据的代码量,我们几乎不需要循环和不关心用户到底是新增还是修改,更不用编写新增和修改以及删除的SQL语句,适配器都帮我们在后台进行了很好的处理.
如果您要通过 SQL Server 存储过程使用 DataAdapter 来编辑或删除数据,请确保不要在存储过程定义中使用 SET NOCOUNT ON。这将使返回的受影响的行数为零,DataAdapter 会将其解释为并发冲突。在许多情况下,以何种顺序向数据源发送通过 DataSet 所做的更改是非常重要的。例如,如果更新了现有行的主键值,并且添加了以新主键值作为外键的新行,则务必要在处理插入之前处理更新。可以使用 DataTable 的 Select 方法来返回仅引用具有特定 RowState 的 DataRow 数组。然后可以将返回的 DataRow 数组传递给 DataAdapter 的 Update 方法来处理已修改的行。通过指定要更新的行的子集,可以控制处理插入、更新和删除的顺序。以下代码确保首先处理表中已删除的行,然后处理已更新的行,然后处理已插入的行。
DataTable table = dataSet.Tables["Customers"];
//第一步处理删除.
adapter.Update(table.Select(null, null, DataViewRowState.Deleted));
//接着处理更新
adapter.Update(table.Select(null, null,
DataViewRowState.ModifiedCurrent));
//最后处理新增
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()方法对数据表进行批量操作了:
SqlCommandBuilder scb = new SqlCommandBuilder(sda);
sda.Update(dt);
完整代码如下:
public static void UpdateDataSet(DataSet ds, string tableName)
{
try
{
if (tableName == "")
{
throw new ArgumentNullException("tableName 不能为空");
}
//生成架构
string selectSQL = string.Format("select * from {0} where 1=2", tableName);
using (SqlDataAdapter sda = new SqlDataAdapter(selectSQL, ConnectionString))
{ SqlCommandBuilder scb = new SqlCommandBuilder(sda); sda.UpdateCommand = scb.GetUpdateCommand();
sda.InsertCommand = scb.GetInsertCommand();
sda.DeleteCommand = scb.GetDeleteCommand(); sda.Update(ds, tableName);
ds.Tables[tableName].AcceptChanges();
DisposeCommand(sda.UpdateCommand);
DisposeCommand(sda.InsertCommand);
DisposeCommand(sda.DeleteCommand);
sda.Dispose();
scb.Dispose();
}
}
catch (SqlException e)
{
throw e;
}
}
为了确保在用户编辑完成后,立刻将数据同步到数据集中,必须调用bindingSource的EndEdit方法来同步数据.
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
this.bindingSource.EndEdit();
}
在窗体加载时,调用刷新方法,然后程序会自动将数据绑定到DataGridView上:
private bool fnRefresh()
{
string sql = string.Format("select * from myUser");
CM.Products.DataAccess.SqlHelper.GetDataTableBySQL(this.dsUser.myUser, sql);
return true;
}
我们可以通过DataGridView的EndEdit方法来获取当前用户是否已经结束编辑:
bool isEnd= this.dataGridView1.EndEdit();
另外可以通过GetChanges()方法来获取修改的数据,返回一个DataTable.
1 DataTable dtModify = this.dsUser.myUser.GetChanges(DataRowState.Modified);
调用UpdateTable方法,即可对表格进行批量处理(这里就一个表,如果是多个表,那么需要指明表名):
private bool Save()
{
try
{
DataAccess.SqlHelper.UpdateDataSet(this.dsUser, "myUser");
this.dsUser.myUser.AcceptChanges();//提交数据库
return true;
}
catch (Exception ex)
{
return false;
} }
当用户选择一个单元格时,会获取到当前行的索引,然后调用RemoveAt()方法进行删除,由于用bindingSource进行了绑定,可以直接调用save()方法进行数据保存:
private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
{
if (this.dataGridView1.CurrentRow != null)
{
int index = this.dataGridView1.CurrentRow.Index;
if (index > -)
{
this.dataGridView1.Rows.RemoveAt(index);
Save();
}
}
}
当用户单击新增按钮时,我们创建一个强类型的myUserRow,然后给它附上默认值(特别是主键)
//add row
private void toolStripButton1_Click(object sender, EventArgs e)
{
Common.dsUser.myUserRow dr = this.dsUser.myUser.NewmyUserRow();
dr["ID"] = System.Guid.NewGuid().ToString();
dr["Name"] = "Name";
dr["AddTime"] = DateTime.Now.ToString(); this.dsUser.myUser.AddmyUserRow(dr);
}
C#利用SqlDataAdapte对DataTable进行批量数据操作的更多相关文章
- MyBatis的关于批量数据操作的测试
摘录自:http://www.linuxidc.com/Linux/2012-05/60863.htm MyBatis的前身就是著名的Ibatis,不知何故脱离了Apache改名为MyBatis.My ...
- CDH离线数据导入solr:利用MapReduceIndexerTool将json文件批量导入到solr
场景描述:前段时间,将实时数据通过kafka+flume+morphline的方式接入到solr中.新进来的数据已经可以在solr中看到了,但是以前的历史数据还没有导入solr. CDH提供利用Map ...
- 批量插入数据, 将DataTable里的数据批量写入数据库的方法
大量数据导入操作, 也就是直接将DataTable里的内容写入到数据库 通用方法: 拼接Insert语句, 好土鳖 1. MS Sql Server: 使用SqlBulkCopy 2. MySql ...
- java操作Excel之POI(5)利用POI实现使用模板批量导出数据
后台导出方法: 在源文件夹src下面放个准备好的模板:/com/cy/template/userExportTemplate.xls,这个模板有头部一行: /** * 后台导出方法 * 利用POI实现 ...
- SqlBulkCopy将DataTable中的数据批量插入数据库中
#region 使用SqlBulkCopy将DataTable中的数据批量插入数据库中 /// <summary> /// 注意:DataTable中的列需要与数据库表中的列完全一致.// ...
- list转datatable,SqlBulkCopy将DataTable中的数据批量插入数据库
/// <summary> /// 将泛类型集合List类转换成DataTable /// </summary> /// <param name="list&q ...
- 利用Factory-boy和sqlalchemy来批量生成数据库表数据
测试过程中免不了要构造测试数据,如果是单条数据,还比较简单,但如果是批量数据,就比较麻烦了. 最近看到Factory_boy这个python第三方库,它通过SQLAlchemyModelFactory ...
- 利用反射把DataTable自动赋值到Model实体(自动识别数据类型)
转:http://www.cnblogs.com/the7stroke/archive/2012/04/22/2465591.html using System.Collections.Generic ...
- 你好,C++(23) 4.4.2 工资程序成长记:用数组处理批量数据,用循环结构执行重复动作
4.4 从语句到程序 了解了各种表达式和语句之后,就相当于掌握了写作文要用到的词语和句子,但是,仅有词语和句子是无法构成一篇有意义的文章的.要完成一篇文章,先需要确定这篇文章的结构,是先分述再总述, ...
随机推荐
- JSON学习之一
1.JSON:JavaScript Object Notation(javaScript对象表示法),JSON是存储和交换文本信息的语法,类似XML:JSON比XML更小,更快,更易解析: { &qu ...
- 一套后台管理html模版
最近自己需要一套后台管理的模版,然后去网上查找,模版的确很多,但是适合我的并不多.我需要的模版是不会很大,我能够控制代码,样式不要太古朴,最好有点CSS3的效果.最后终于找到一张主页,然后再根据这个主 ...
- Testing - 测试基础 - 用例
测试用例 是指对一项特定的软件产品进行测试任务的描述,体现测试方案.方法.技术和策略. 内容包括测试目标.测试环境.输入数据.测试步骤.预期结果.测试脚本等,并形成文档. 每个具体测试用例都将包括下列 ...
- Bounce.js – 快速创建漂亮的 CSS3 动画效果
Bounce.js 是一个用于制作漂亮的 CSS3 关键帧动画的 JavaScript 库,使用其特有的方式生成的动画效果.只需添加一个组件,选择预设,然后你就可以得到一个短网址或者导出为 CSS 代 ...
- 【知识积累】BufferedImage类实现图片的切分
一.引言 如何实现图片分割?若有园友用到这个模块,使用Java的BufferedImage类来实现,图片切分也可以作为一个小工具积累起来,以备不时之需. 二.代码清单 package com.lees ...
- 玩爽了!直接在Chrome里抓取数据
一个小测试发现可以自动做题,于是想通过脚本的方式看能不能获取相应的题库,刚好可以学习一下JS异步操作.花了一天时间,总算跑顺利了,遇到了不少坑.记录下来分享. 1.JS如何顺序执行 JS有强大的异步操 ...
- 遗传算法的简单应用-巡回旅行商(TSP)问题的求解
上篇我们用遗传算法求解了方程,其中用到的编码方式是二进制的编码,实现起来相对简单很多, 就连交配和变异等操作也是比较简单,但是对于TSP问题,就稍微复杂一点,需要有一定的策略, 才能较好的实现. 这次 ...
- 【原创】Lucene.Net+盘古分词器(详细介绍)
本章阅读概要 1.Lucenne.Net简介 2.介绍盘古分词器 3.Lucene.Net实例分析 4.结束语(Demo下载) Lucene.Net简介 Lucene.net是Lucene的.net移 ...
- Mac下github项目检出与提交
项目检出 如果你的git还没有代码仓库,可以用过git的代码仓库页面新建一个你的仓库 创建git上的仓库后,我们还需要建立本地的仓库,所以打开Mac终端,建立本地仓库文件夹(这里我用HelloC),然 ...
- nodejs中exports与module.exports的实践
只要是在nodejs中写自己的文件模块就少不了会遇到module.exports和exports的使用,看别人的代码大多都会使用“module.exports=exports=<对象/函数等&g ...