ADO.NET- 中批量添加数据的几种实现方法比较
在.Net中经常会遇到批量添加数据,如将Excel中的数据导入数据库,直接在DataGridView控件中添加数据再保存到数据库等等。
方法一:一条一条循环添加
通常我们的第一反应是采用for或foreach循环一条一条的添加。这样的方法可想而知,效率肯定很低,可以慢到操作人员无法接受的那种。经过测试(局域网),1W条数据将会耗时3分42秒842毫秒
for (int i = ; i < dgv.Rows.Count; i++)
{
string sql = "insert into .....";
SqlHelper.ExcuteNonQuery(CommandType.Text, sql, null);
}
方法二:每一千条循环添加
也许马上会有人想到Insert多条记录,即"Insert into TableName Values(' ',' ',' '),Values(' ',' ',' ')",这种方法在一定程度上提高不少的效率,但是这种方法有几个弊端。比如说,在SQL Server 2000中它就不支持这种语法,会提示"第 2 行: ',' 附近有语法错误。"的警告,批量操作也就无从谈起。再比如,这种方法么次最多也只能Insert 1000条数据,如果超过了1000条就会报错:"INSERT 语句中行值表达式的数目超出了 1000 行值的最大允许值。"。当然了,我们可以分为几次,每次添加一千条数据,这样还是比方法一的效率高不少。经过测试(局域网),1W条数据将会耗时0分14秒766毫秒
int rowCount = dataGridView1.Rows.Count;
int quotient = rowCount / ; //商
int remainder = rowCount % ; //余数
StringBuilder str = new StringBuilder();
for (int j = ; j < quotient; j++)
{
str.Append("insert into BatchTable values");
for (int i = ; i < ; i++)
{
str.AppendFormat("('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}'),"
, dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value,
dataGridView1[, i].Value , dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value,
dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value);
}
string sql = str.ToString().TrimEnd(',');
SqlHelper.ExcuteNonQuery(CommandType.Text, sql, null);
str.Clear();
}
if (remainder > )
{
str.Append("insert into BatchTable values");
for (int i = ; i < remainder; i++)
{
str.AppendFormat("('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}'),"
, dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value
, dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value,
dataGridView1[, i].Value, dataGridView1[, i].Value, dataGridView1[, i].Value);
}
string sql = str.ToString().TrimEnd(',');
SqlHelper.ExcuteNonQuery(CommandType.Text, sql, null);
str.Clear();
}
方法三:使用SqlBulkCopy类批量添加数据
SqlBulkCopy类位于System.Data.SqlClient命名空间下,摘自MSDN:Microsoft SQL Server 提供一个称为 bcp 的流行的命令提示符实用工具,用于将数据从一个表移动到另一个表(表既可以在同一个服务器上,也可以在不同服务器上)。SqlBulkCopy 类允许编写提供类似功能的托管代码解决方案。还有其他将数据加载到 SQL Server 表的方法(例如 INSERT 语句),但相比之下SqlBulkCopy 提供明显的性能优势。使用 SqlBulkCopy 类只能向 SQL Server 表写入数据。但是,数据源不限于 SQL Server;可以使用任何数据源,只要数据可加载到 DataTable 实例或可使用IDataReader 实例读取数据。
采用 SqlBulkCopy类进行批量添加数据将会大大调高效率。经过测试(局域网),1W条数据将会耗时0分0秒292毫秒
public static bool ExcuteNonQuery(DataTable dt)
{
SqlConnection connection = new SqlConnection(connString);
connection.Open();
SqlBulkCopy sqlbulkcopy = new SqlBulkCopy(connection);
sqlbulkcopy.BulkCopyTimeout = ; //超时之前操作完成所允许的秒数
sqlbulkcopy.BatchSize = dt.Rows.Count; //每一批次中的行数
sqlbulkcopy.DestinationTableName = dt.TableName; //服务器上目标表的名称
for (int i = ; i < dt.Columns.Count; i++)
{
sqlbulkcopy.ColumnMappings.Add(i, i); //映射定义数据源中的列和目标表中的列之间的关系
}
sqlbulkcopy.WriteToServer(dt); // 将DataTable数据上传到数据表中
connection.Close();
return true;
}
方法四:利用SQL Server 2008新特性:表值参数,简称TVPS
MSDN中对表值参数的解释:
表值参数提供一种将客户端应用程序中的多行数据封送到 SQL Server 的简单方式,而不需要多次往返或特殊服务器端逻辑来处理数据。 您可以使用表值参数来包装客户端应用程序中的数据行,并使用单个参数化命令将数据发送到服务器。 传入的数据行存储在一个表变量中,然后您可以通过使用 Transact-SQL 对该表变量进行操作。
注意:无法在表值参数中返回数据。 表值参数是只可输入的参数;不支持 OUTPUT 关键字。详情请参见MSDN
在ADO.NET中使用表值参数传递DataTable对象
1、创建数据表对应的表值参数类型,此类型应与数据表结构一致,假如创建数据表的sql语句为
--BatchTable为数据表名称
create table [dbo].[BatchTable](
[Gradation] [nvarchar](10) NULL,
[Column1] [nvarchar](10) NULL,
[Column2] [nvarchar](10) NULL,
[Column3] [nvarchar](10) NULL,
[Column4] [nvarchar](10) NULL,
[Column5] [nvarchar](10) NULL,
[Column6] [nvarchar](10) NULL,
[Column7] [nvarchar](10) NULL,
[Column8] [nvarchar](10) NULL,
[Column9] [nvarchar](10) NULL,
[Column10] [nvarchar](10) NULL
) ON [PRIMARY]
GO
2、那么对应的创建表值参数类型的语句为
--BatchTableTvps为参数类型名称
Create type BatchTableTvps as Table
(
[Gradation] [nvarchar](10) NULL,
[Column1] [nvarchar](10) NULL,
[Column2] [nvarchar](10) NULL,
[Column3] [nvarchar](10) NULL,
[Column4] [nvarchar](10) NULL,
[Column5] [nvarchar](10) NULL,
[Column6] [nvarchar](10) NULL,
[Column7] [nvarchar](10) NULL,
[Column8] [nvarchar](10) NULL,
[Column9] [nvarchar](10) NULL,
[Column10] [nvarchar](10) NULL
)
GO
懒人们一般的做法都是,选中要操作的数据表,单击右键 —> 编写表脚本为 —> Create到 —> 新查询编辑器窗口。然后稍稍修改就行了
3、然后就可以在C#中指定SqlParameter参数对象的属性TypeName为刚刚创建的表值参数类型。
DataTable table = GetDataTable("BatchTable"); //要插入的表
string sql = "insert into BatchTable select * from @BatchTable";
SqlParameter par = new SqlParameter("@BatchTable", SqlDbType.Structured);
par.TypeName = "BatchTableTvps"; //指定表值参数类型
par.Value = table;
SqlParameter[] pars = new SqlParameter[] { par };
int values = SqlHelper.ExcuteNonQuery(CommandType.Text, sql, pars);
SqlBulkCopy类批量添加数据与表值参数TVPS批量添加数据比较
同一环境下,添加1W条数据:SqlBulkCopy耗时292毫秒,TVPS耗时902毫秒
同一环境下,添加10W条数据:SqlBulkCopy耗时5秒768毫秒,TVPS耗时6秒617毫秒
同一环境下,添加20W条数据:SqlBulkCopy耗时11秒791毫秒,TVPS耗时16秒525毫秒
测试源码下载链接:http://download.csdn.net/detail/tracine0513/8060011
ADO.NET- 中批量添加数据的几种实现方法比较的更多相关文章
- .Net中批量添加数据的几种实现方法比较
在.Net中经常会遇到批量添加数据,如将Excel中的数据导入数据库,直接在DataGridView控件中添加数据再保存到数据库等等. 方法一:一条一条循环添加 通常我们的第一反应是采用for或for ...
- (转载)MySQl数据库-批量添加数据的两种方法
方法一:使用excel表格 方法二:使用insert语句(FileWriter批量写入) 使用excel表格 1.打开数据表,按照表的字段在excel中添加数据.注意:表中字段名必须和excel中的名 ...
- SQLSERVER数据库中批量导入数据的几种方法
第一:使用Select Into 语句 如果企业数据库都是采用SQL Server数据库的话,则可以利用select into语句实现数据的导入. select into语句的作用是把数据从另外一个数 ...
- Java模拟数据量过大时批量处理数据的两种实现方法
方法一: 代码如下: import java.util.ArrayList; import java.util.List; /** * 模拟批量处理数据(一) * 当数据量过大过多导致超时等问题可以将 ...
- mybatis 批量添加数据的两种实现方式
做开发的这几年期间经常遇到类似处理这种形式数据的问题,也遇到很多刚刚入行的新同学,发现他们做处理这块,经验不够,今天特地整理了一下,大家都会遇到的几种情况,代码也都粘贴出来了,拿去不谢,有时间大家还是 ...
- mybatis批量添加数据的三种方式
原文地址:https://www.cnblogs.com/gxyandwmm/p/9565002.html
- spring boot之使用通用Mapper批量添加数据
通用Mapper是一款针对mybatis进行扩展的轻量级组件,使用起来非常方便.当调用其针对mysql进行批量添加数据的方法时,发现报错,仔细研究了一番,发现是在使用通用Mapper上出现了问题.下面 ...
- Yii2如何批量添加数据
批量添加这个操作,在实际开发中经常用得到,今天小编抽空给大家整理些有关yii2批量添加的问题,感兴趣的朋友一起看看吧. 在上篇文章给大家介绍了关于浅析Yii2 gridview实现批量删除教程,当然, ...
- EF批量添加数据性能慢的问题的解决方案
//EF批量添加数据性能慢的问题的解决方案 public ActionResult BatchAdd() { using (var db = new ToneRoad.CEA.DbContext.Db ...
随机推荐
- 【Codeforces Round #433 (Div. 2) A】Fraction
[链接]h在这里写链接 [题意] 在这里写题意 [题解] 枚举分子从高到低就好. 这样得到的一定是最大的. (可以约分没错,但是约分过后和就不是n了,所以不会有错的) [错的次数] 0 [反思] 在这 ...
- 关于mysql事务行锁for update实现写锁的功能
关于mysql事务行锁for update实现写锁的功能 读后感:用切面编程的理论来讲,数据库的锁对于业务来说是透明的.spring的事务管理代码,业务逻辑代码,表锁,应该是三个不同的设计层面. 在电 ...
- sqoop 1.4.4-cdh5.1.2快速入门 分类: C_OHTERS 2015-06-06 11:40 208人阅读 评论(0) 收藏
一.快速入门 (一)下载安装 1.下载并解压 wget http://archive.cloudera.com/cdh5/cdh/5/sqoop-1.4.4-cdh5.1.2.tar.gz tar - ...
- 20、在PC上测试虚拟驱动vivi
在Ubuntu上测试 准备工作:安装xawtv(是一个应用程序,用来在Ubuntu上捕获摄像头数据并显示)sudo apt-get install xawtv 源码xawtv-3.95.tar.gz: ...
- eclipse调试鼠标放上去显示变量值
在eclipse中调试时,鼠标移动到变量上不显示值,这个原来自己也遇到过,没注意,反正就使用ctrl+shift+i嘛,也可以的,刚查了一下,解决方法如下: Window->Preference ...
- php实现求链表中倒数第k个节点
php实现求链表中倒数第k个节点 一.总结 $head = $head->next; //1.将$head节点next域里面的记录的那个地址值($head节点的下一个节点的地址)给$head,$ ...
- window下利用navicat访问Linux下的mariadb数据库
1.再Linux上成功安装mariadb数据库后,不管是在dos(敲命令mysql -h192.168.136.8 -uroot -p)下或者是navicat(创建连接)下连接mariadb数据库,会 ...
- 终端复用工具tmux的使用
tmux的作用在于终端复用. 1. 在server上启动一个bash.并在里面执行tmux 2. 通过ssh远程登录server,执行tmux attach,就会切换到server上的那个bash中, ...
- c# 调用ArcEngine的GP工具
转自原文c# 调用ArcEngine的GP工具,AE调用GP工具 IAoInitialize m_AoInitialize = new AoInitializeClass(); esriLicense ...
- [Typescript] Generics using TypeScript
In this lesson we cover the key reason why programming languages need generics. We then show how use ...