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 ...
随机推荐
- 【CS Round #48 (Div. 2 only)】Dominant Free Sets
[链接]h在这里写链接 [题意] 让你在n个点组成的集合里面选取不为空的集合s. 使得这里面的点没有出现某个点a和b,ax>=bx且ay>=by; 问你s的个数. [题解] 我们把这些点按 ...
- Java FutureTask Example Program(Java FutureTask例子)
Sometime back I wrote a post about Java Callable Future interfaces that we can use to get the concur ...
- [React] Style a React component with styled-components
In this lesson, we remove the mapping between a React component and the styles applied to it via cla ...
- 对inetd、xinetd与TCP_Wrapper的基本了解
在Linux系统中有一个特殊的守护进程inetd(InterNET services Daemon),它用于Internet标准服务,通常在系统启动时启动.通过命令行可以给出inetd的配置文件,该配 ...
- 9.6 Binder系统_驱动情景分析_server的多线程实现
当多个client对server发出请求的时候,如果server忙不过来的时候会创建多线程来处理请求 那么忙不过来由谁来判断? server进程有个binder_proc结构体,其里面有todo链表( ...
- Shiro基础知识08----拦截器介绍(转)
1 拦截器介绍 Shiro使用了与Servlet一样的Filter接口进行扩展:所以如果对Filter不熟悉可以参考<Servlet3.1规范>http://www.iteye.com/b ...
- 分类算法简介 分类: B10_计算机基础 2015-03-09 11:08 257人阅读 评论(0) 收藏
一.决策树 决策树是用于分类和预测的主要技术之一,决策树学习是以实例为基础的归纳学习算法,它着眼于从一组无次序.无规则的实例中 推理出以决策树表示的分类规则.构造决策树的目的是找出属性和类别间的关系, ...
- Node.js v10.1.0 Documentation
Modules Stable 在 Node.js 模块系统中,每个文件都会被当做一个独立的模块.假设有一个名为 foo.js: const circle = require('./circle.js' ...
- Vue源码--解读vue响应式原理
原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...
- Linux下图形界面调试工具kdbg安装及測试
1.Ubuntu系统下安装 Ubuntu系统安装比較方便,直接apt-get即可 apt-get install kdbg 2.centos 安装 首先,在这个地址下下载rpm包.然后使用rpm命令安 ...