在.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- 中批量添加数据的几种实现方法比较的更多相关文章

  1. .Net中批量添加数据的几种实现方法比较

    在.Net中经常会遇到批量添加数据,如将Excel中的数据导入数据库,直接在DataGridView控件中添加数据再保存到数据库等等. 方法一:一条一条循环添加 通常我们的第一反应是采用for或for ...

  2. (转载)MySQl数据库-批量添加数据的两种方法

    方法一:使用excel表格 方法二:使用insert语句(FileWriter批量写入) 使用excel表格 1.打开数据表,按照表的字段在excel中添加数据.注意:表中字段名必须和excel中的名 ...

  3. SQLSERVER数据库中批量导入数据的几种方法

    第一:使用Select Into 语句 如果企业数据库都是采用SQL Server数据库的话,则可以利用select into语句实现数据的导入. select into语句的作用是把数据从另外一个数 ...

  4. Java模拟数据量过大时批量处理数据的两种实现方法

    方法一: 代码如下: import java.util.ArrayList; import java.util.List; /** * 模拟批量处理数据(一) * 当数据量过大过多导致超时等问题可以将 ...

  5. mybatis 批量添加数据的两种实现方式

    做开发的这几年期间经常遇到类似处理这种形式数据的问题,也遇到很多刚刚入行的新同学,发现他们做处理这块,经验不够,今天特地整理了一下,大家都会遇到的几种情况,代码也都粘贴出来了,拿去不谢,有时间大家还是 ...

  6. mybatis批量添加数据的三种方式

    原文地址:https://www.cnblogs.com/gxyandwmm/p/9565002.html

  7. spring boot之使用通用Mapper批量添加数据

    通用Mapper是一款针对mybatis进行扩展的轻量级组件,使用起来非常方便.当调用其针对mysql进行批量添加数据的方法时,发现报错,仔细研究了一番,发现是在使用通用Mapper上出现了问题.下面 ...

  8. Yii2如何批量添加数据

    批量添加这个操作,在实际开发中经常用得到,今天小编抽空给大家整理些有关yii2批量添加的问题,感兴趣的朋友一起看看吧. 在上篇文章给大家介绍了关于浅析Yii2 gridview实现批量删除教程,当然, ...

  9. EF批量添加数据性能慢的问题的解决方案

    //EF批量添加数据性能慢的问题的解决方案 public ActionResult BatchAdd() { using (var db = new ToneRoad.CEA.DbContext.Db ...

随机推荐

  1. jQuery常用的API

    1.jQuery给标签添加子元素(父子关系) jQuery对象.append("子"); 将div标签插入到ul标签之后 $("ul").append($('d ...

  2. mysql三种带事务批量插入

    原文:mysql三种带事务批量插入 c#之mysql三种带事务批量插入 前言 对于像我这样的业务程序员开发一些表单内容是家常便饭的事情,说道表单 我们都避免不了多行内容的提交,多行内容保存,自然要用到 ...

  3. 解题报告 之 HDU5305 Friends

    解题报告 之 HDU5305 Friends Description There are  people and  pairs of friends. For every pair of friend ...

  4. VS2012调试C++工程DLL

    1.C++工程属性对话框 2.配置属性: (1)常规:输出目录:..\Bin\WFCrawler(调用DLL的工程)            中间目录:..\Bin\WFCrawler(调用DLL的工程 ...

  5. 23种设计模式——Prototype模式

    Prototype模式是提供自我复制的功能.包括浅拷贝和深拷贝. 一.Prototype模式的用途 场景1:游戏场景中有很多类似的敌人,它们的技能都一样,但是随着敌人出现的位置和不同,它们的能力也不太 ...

  6. iOS将汉字转换为拼音

    将汉字转换为拼音 - (NSString *)chineseToPinyin:(NSString *)chinese withSpace:(BOOL)withSpace { CFStringRef h ...

  7. ASP.NET MVC中实现多个button提交的几种方法

    有时候会遇到这样的情况:在一个表单上须要多个button来完毕不同的功能,比方一个简单的审批功能. 假设是用webform那不须要讨论,但asp.net mvc中一个表单仅仅能提交到一个Action处 ...

  8. php实现把二叉树打印成多行(谋而后动,写好算法思路,不然浪费超多时间而且还是错误代码,而且精力消耗会导致代码正确率下降以及低级错误)

    php实现把二叉树打印成多行(谋而后动,写好算法思路,不然浪费超多时间而且还是错误代码,而且精力消耗会导致代码正确率下降以及低级错误) 一.总结 要点:a.层次遍历(队列)  b.层次遍历中的层次(孩 ...

  9. 用Ajax图片上传、预览、修改图片

    首选图片的上传和下载并不是很难,但要注意细节. 一,给出前端图片上传的html代码 1.图片上传的控件 <img src="/${res}/images/default.png&quo ...

  10. margin隐藏最后的切割线

    <style> *{margin: 0;padding: 0;} #demo li{ border-bottom: 1px solid #ccc; } #demo ul{ margin-b ...