意外发现的大批量导入数据SqlBulkCopy类
因为要做一个号码归属地查询小功能,因为要导入外部(文本文件)的电话归属地数据,使用的是SqlDataAdapter类,数据不多,只四万有多条,表也只有一个,phoneBook表,使用的是DataTable和SqlDataAdapter,测试了三次导入,平均18秒,但是我觉得太慢了,就百度了下【SQL Server批量导入数据】,发现了SqlBulkCopy这个神器,一秒内导入。
SqlBulkCopy 这个类用于数据库大批量的数据传递,通常用于新旧数据库之间的更新。关键的一点是,即使表结构不同,也可以通过表字段或者字段位置建立映射关系,将所需的数据导入到目标数据库。
下面代码测试了数据量为一百万条数据,几次测试耗时8秒左右。
/// <summary>
/// SqlBulkCopy类的使用,批量更新数据
/// </summary>
public static void SqlBulkCopyDemo()
{
String connStr = ConfigurationManager.ConnectionStrings["connStr"].ToString();
//从数据库中获得表结构和数据
DataTable student = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter("select * from student", connStr);
adapter.Fill(student);
//向表中添加数据
DataRow dr;
Random r = new Random();
Stopwatch st = new Stopwatch();
for(int i = 0; i<1000000; i++)//一百万条数据
{//数据表中的列:name,no,age,sex
dr = student.NewRow();
dr[0] = "小花" + i;
dr[1] = 108 + i;
dr[2] = r.Next(9, 40);//这里是因为数据表中有约束,
dr[3] = (i % 2 == 0 ? "男" : "女");//这个也是有约束
student.Rows.Add(dr);
}
SqlBulkCopy bulk = new SqlBulkCopy(connStr);
bulk.DestinationTableName = "student";//设置目标表,这里是数据库中的student表
bulk.ColumnMappings.Add(0, 0);//建立映射关系
bulk.ColumnMappings.Add(1, 1);
bulk.ColumnMappings.Add(2, 2);
bulk.ColumnMappings.Add(3, 3);
st.Start();//开始计时
bulk.WriteToServer(student.GetChanges());
st.Stop();//结束计时
Console.WriteLine("数据插入成功,耗时为:" + st.ElapsedMilliseconds + "毫秒");
}
测试了三次,结果如下:



1、SqlBulkCopy类的构造方法
其中: conn表示一个SqlConnection对象
connStr表示数据库连接字符串
- SqlBulkCopy(conn)
- SqlBulkCopy(connStr)
- SqlBulkCopy(connStr, SqlBulkCopyOptions copyOptions)
- SqlBulkCopy(conn, SqlBulkCopyOptions copyOptions, SqlTransaction externalTransaction)
其中还有几个陌生的对象:SqlBulkCopyOptions 和 SqlTransaction
1.1、SqlBulkCopyOptions类
这个类是一个枚举类型:
| 对象 | 值 | 备注 |
| Default | 0 | |
| KeepIdentity | 1 | 保留源标识值。 如果未指定,则由目标分配标识值。 |
| CheckConstraints | 2 | 在插入数据的同时检查约束。 默认情况下,不检查约束。 |
| TableLock | 4 | 在批量复制操作期间获取批量更新锁。 如果未指定,则使用行锁。 |
| KeepNulls | 8 | 保留目标表中的空值,而不管默认值的设置如何。 如果未指定,则空值将由默认值替换(如果适用) |
| FireTriggers | 16 | 指定后,会导致服务器为插入到数据库中的行激发插入触发器。 |
| UseInternalTransaction | 32 |
如果已指定,则每一批批量复制操作将在事务中进行。 如果指示了此选项,并且为构造函数提供了 System.Data.SqlClient.SqlTransaction对象,则发生 System.ArgumentException(参数异常)。因为两个事务冲突了。 |
1.2、SqlTransaction类
这个类是事务类,是个密封类,实现了DbTransaction抽象类
2、SqlBulkCopy类的常用属性
| 属性名 | 功能 | 备注 |
| BatchSize | 设置或获取每达到多少行就更新到服务器(也就是目标表) | 值为int, |
| BulkCopyTimeout | 设置或获取超时时间 | 默认30秒,如果设置成0,将无限制等待, 值为int,单位为秒 |
| DestinationTableName | 设置或获取服务器上的目标表的名称 | 也就是批量更新的目标表, 值为String类型 |
| EnableStreaming | 设置或获取是否支持传输 IDataReader 对象的数据 | true为支持, 值为bool类型 |
| NotifyAfter | 设置或获取在生成通知事件之前要处理的行数 | 默认为0, 值为int类型, |
| ColumnMappings | 获取列映射定义数据源中的列和目标表中的列之间的映射关系 | 返回值为SqlBulkCopyColumnMappingCollection |
2.1、表中的SqlBulkCopyColumnMappingCollection类型是一个映射集合类,是目标表的列和源表的列的映射关系的集合。
这个类是一个密封类,不能被继承,实现了一个CollectionBase抽象类。
SqlBulkCopyColumnMappingCollection没有提供构造方法,我们也不需要去newat的对象,主要是使用它的几个重载的Add()方法
Add()有五个重载的方法:
- SqlBulkCopyColumnMapping Add(SqlBulkCopyColumnMapping bulkCopyColumnMapping);
- SqlBulkCopyColumnMapping Add(string sourceColumn, string destinationColumn);
- SqlBulkCopyColumnMapping Add(int sourceColumnIndex, string destinationColumn);
- SqlBulkCopyColumnMapping Add(string sourceColumn, int destinationColumnIndex);
- SqlBulkCopyColumnMapping Add(int sourceColumnIndex, int destinationColumnIndex);
其中四个方法是类似的,都是对应的列名或者列的位置。
第一个方法是添加一个已经构建好的SqlBulkCopyColumnMapping对象,
他也有集合常用的方法:
| 方法名 | 功能 | 备注 |
| Clear(); | 清除集合中的映射关系 | |
| Contains(SqlBulkCopyColumnMapping value); | 判断是否包含指定映射关系 | |
| IndexOf(SqlBulkCopyColumnMapping value); | 返回指定映射关系的位置 | |
| Remove(SqlBulkCopyColumnMapping value); | 移除指定映射关系 | |
| RemoveAt(int index); | 移除指定位置的映射关系 | |
| Insert(int index, SqlBulkCopyColumnMapping value); | 在指定位置插入映射关系 | |
| CopyTo(SqlBulkCopyColumnMapping[] array, int index); | 从指定位置开始将映射关系复制到指定数组中 | index指定的集合中的位置, 而不是数组中的角标 |
3、SqlBulkCopy类的常用方法
- WriteToServer,这个方法重载了四次,功能是将数据写到目的表中。
| WriteToServer(DataRow[] rows); | 将 DataRow 数组所有元素写到目标表中 |
| WriteToServer(DataTable table); | 将 DataTable 所有行写到目标表中 |
| WriteToServer(IDataReader reader); | 将指定的 IDataReader 对象中的数据写到目标表中 |
| WriteToServer(DataTable table, DataRowState rowState); | 将 DataTable 中指定状态的所有行写到目标表中 |
【上表中的 DataRowState 状态行可以参考这篇博客DataTable的AcceptChanges()方法和DataRow的RowState属性】
这个类还提供了八个异步写的方法,我还没全部理解,就不放上来了。
既然能够有写的操作,那这个类应该类似于流,它还有一个Close()方法,用于关闭 SqlBulkCopy 实例。
意外发现的大批量导入数据SqlBulkCopy类的更多相关文章
- 大批量导入数据的SqlBulkCopy类
SqlBulkCopy 这个类用于数据库大批量的数据传递,通常用于新旧数据库之间的更新.关键的一点是,即使表结构不同,也可以通过表字段或者字段位置建立映射关系,将所需的数据导入到目标数据库. 下面代 ...
- IBatis.Net 下使用SqlBulkCopy 大批量导入数据 问题解决
SQLBulkCopy是继承SQLClient空间下的一个特殊类,它可以帮助我们以映射的方式把DataTable和DataReader数据大批量导入到数据库对应表中 public void Inert ...
- Java不写文件,LOAD DATA LOCAL INFILE大批量导入数据到MySQL的实现(转)
MySQL使用load data local infile 从文件中导入数据比insert语句要快,MySQL文档上说要快20倍左右.但是这个方法有个缺点,就是导入数据之前,必须要有文件,也就是说从文 ...
- Excel大批量导入数据到SQLServer数据库-万条只用1秒
private string ExcelToStudent() { /*---*/ var preStr = DateTime.Now.ToString("yyyyMMddHHmmssfff ...
- 读取接口XML和批量导入数据SqlBulkCopy
首先是C#处理xml文档 string urlStr = string.Format("http://……?timeBeg={0}&timeEnd={1}", timeBe ...
- C#中大批量导入数据SqlBulkCopy
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...
- 使用BCP批量导入数据
本文原创,转载请标明出处 BCP 工具的使用 The bulk copy program utility (bcp) bulk copies data between an instance of M ...
- SqlLite用SQLiteTransaction快速导入数据
mysql与sql server都有整表导入的类库,但是查遍了资料发现sqlLite没有,除非自己去写个,发现用SQLiteTransaction导入数据也很快,附上代码 /// <summar ...
- C# SqlBulkCopy类批量导入数据
特别注意 sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName); 插入的时候列的顺序可 ...
随机推荐
- nginx : server_name localhost 和 chrome : Provisional headers are shown
问题相关问题现象:解决思路解决方案总结 问题相关 nginx : server_name localhost chrome : Provisional headers are shown 问题现象: ...
- redis-如何在工程中使用redis
这里,我们介绍下如何使用redis作为缓存服务器使用在我们的工程中. 使用思路 对于java中的使用redis提供了一个jedis的jar包.我们在安装好我们的redis服务器以后,只需要通过redi ...
- python之列表对象
1. 获取列表中的某个值 描述:获取下标所对应的值 语法: print(li[0]) #[取索引值] 样例: li = list(['a','b','c']) val=(li[0]) #获取下标所对应 ...
- ZooKeeper的不同类型的Znodes
在ZooKeeper中有3个不同类型的znodes:persistent, ephemeral, sequential Persistent Znodes(默认)在ZooKeeper中,这是默认的zn ...
- [Android] "Failed to find Java version for 'C:\Windows\system32\java.exe"
Impossible to install SDK r17 on win 7 x64 "Failed to find Java version for 'C:\Windows\system3 ...
- Python求解登楼梯问题(京东2016笔试题)
问题:假设一段楼梯共15个台阶,小明一步最多能上3个台阶,那么小明上这段楼梯一共有多少种方法? 解析:从第15个台阶上往回看,有3种方法可以上来(从第14个台阶上一步迈1个台阶上来,从第13个台阶上一 ...
- barmanager工具栏及gridcontrol部分属性设置
1.工具栏部分属性设置,如:右键菜单,禁止移动等 2.gridControl属性设置,如选中行颜色,禁止移动隐藏等
- android学习5——画图问题
重写View中的onDraw函数可以实现画图.代码如下: @Override public void onDraw(Canvas canvas) { Paint paint = new Paint() ...
- [译]如何在Web开发中使用Python
[译]如何在Web开发中使用Python 原文:HOWTO Use Python in the Web 摘要 这篇文档展示了Python如何融入到web中.它介绍了几种Python结合web服务器的方 ...
- 【转】对于HttpClient和HtmlUnit的理解
原文地址:http://www.haohaoblog.com/?p=1327&utm_source=tuicool 做Java编程的人其实,很多不懂SEO,也不知道如何让百度收录等等,当然,对 ...