第二十一节:ADO层次上的海量数据处理方案(SqlBulkCopy类插入和更新)
一. 简介
1. 背景:
虽然前面EF的扩展插件Z.EntityFramework.Extensions,性能很快,而且也很方便,但是该插件要收费,使用免费版本的话,需要定期更新,如果不更新,将失效,非常麻烦,这个时候SqlBulkCopy类既免费又高效,显得非常合适了。
2. 使用步骤:
①. 引入命名空间:using System.Data.SqlClient;
②. 使用DataTable构造与目标数据库表结构相同的字段,并给其赋值。
③. 使用SqlBulkCopy类,将内存表中的数据一次性插入到目标表中。(看下面的封装可知,可以自行设置插入块的大小)
补充:调用下面的封装这种形式必须内存表中的字段名和数据库表中的字段名一一对应。
二. 使用方式及其性能测试
1. 涉及到的数据库结构:

2. 数据库连接字符串
<add name="CodeFirstModel2" connectionString="data source=localhost;initial catalog=EFDB2;persist security info=True;user id=sa;password=123456;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
3. 代码实践
有两种插入方式,一种是按部就班的每个字段 内存表和数据表进行映射,这个情况无须名称一致,只要映射正确即可。另外一种方式是,直接调用下面的封装方法即可,这种要求内存表中字段和数据库表中的字段名称必须完全一致,一一对应,这样就省去了方法一 中一一匹配映射的繁琐步骤了。
public class SqlBulkCopyTest
{
public static void TestSqlBulkCopy()
{
//一. 构造DataTable结构并且给其赋值
//1.定义与目标表的结构一致的内存表 排除自增id列
DataTable dtSource = new DataTable();
//列名称如果和目标表设置为一样,则后面可以不用进行字段映射
dtSource.Columns.Add("id");
dtSource.Columns.Add("t21");
dtSource.Columns.Add("t22");
//2. 向dt中增加4W条测试数据
DataRow dr;
for (int i = ; i <; i++)
{
// 创建与dt结构相同的DataRow对象
dr = dtSource.NewRow();
dr["id"] = Guid.NewGuid().ToString("N");
dr["t21"] = "Name" + i;
dr["t22"] = "Address" + i;
// 将dr追加到dt中
dtSource.Rows.Add(dr);
}
//二.将内存表dt中的4W条数据一次性插入到t_Data表中的相应列中
System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
st.Start();
string connStr = ConfigurationManager.ConnectionStrings["CodeFirstModel2"].ToString(); #region 01-按部就班一一对应
//{
// using (SqlBulkCopy copy = new SqlBulkCopy(connStr))
// {
// //1 指定数据插入目标表名称
// copy.DestinationTableName = "TestTwo"; // //2 告诉SqlBulkCopy对象 内存表中的 字段和目标表中的字段 对应起来(这里有多个重载,也可以用索引对应)
// //前面是内存表,后面是目标表即数据库中的字段
// copy.ColumnMappings.Add("id", "id");
// copy.ColumnMappings.Add("t21", "t21");
// copy.ColumnMappings.Add("t22", "t22"); // //3 将内存表dt中的数据一次性批量插入到目标表中
// copy.WriteToServer(dtSource);
// }
//} #endregion #region 02-调用封装
{
AddByBluckCopy(connStr, dtSource, "TestTwo");
}
#endregion st.Stop();
Console.WriteLine("数据插入成功,总耗时为:" + st.ElapsedMilliseconds + "毫秒"); } /// <summary>
/// 海量数据插入方法
/// (调用该方法需要注意,DataTable中的字段名称必须和数据库中的字段名称一一对应)
/// </summary>
/// <param name="connectstring">数据连接字符串</param>
/// <param name="table">内存表数据</param>
/// <param name="tableName">目标数据的名称</param>
public static void AddByBluckCopy(string connectstring,DataTable table, string tableName)
{
if (table != null && table.Rows.Count > )
{
using (SqlBulkCopy bulk = new SqlBulkCopy(connectstring))
{
bulk.BatchSize = ;
bulk.BulkCopyTimeout = ;
bulk.DestinationTableName = tableName;
bulk.WriteToServer(table);
}
}
}
}
4. 性能测试的结论

根据上述的数据测试可以看出来,SqlBulkCopy在处理大数据量插入上速度非常快,甚至比付费的插件Z.EntityFramework.Extensions都要快,所以值得参考和推荐。
既然SqlBulkCopy解决大数据量的插入问题,那么删除和更新怎么办呢? 详见 第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,如需代码请留下你的评论,加我QQ:604649488 (备注:评论的博客名)
第二十一节:ADO层次上的海量数据处理方案(SqlBulkCopy类插入和更新)的更多相关文章
- centos LAMP第三部分php,mysql配置 php配置文件 配置php的error_log 配置php的open_basedir 安装php的扩展模块 phpize mysql配置第二十一节课
centos LAMP第三部分php,mysql配置 php配置文件 配置php的error_log 配置php的open_basedir 安装php的扩展模块 phpize mysql配 ...
- 风炫安全WEB安全学习第二十一节课 存储型XSS讲解
风炫安全WEB安全学习第二十一节课 存储型XSS讲解 存储型XSS演示 存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存 ...
- 第二十一节,使用TensorFlow实现LSTM和GRU网络
本节主要介绍在TensorFlow中实现LSTM以及GRU网络. 一 LSTM网络 Long Short Term 网络—— 一般就叫做 LSTM ——是一种 RNN 特殊的类型,可以学习长期依赖信息 ...
- 【php增删改查实例】第二十一节 - 用户修改功能
19.1 添加用户修改的按钮 打开userManage.html,找到新增按钮的地方: 我们不难发现,编辑按钮就差不多应该在新建用户的右边. 那么,假如我现在是新人,对这个项目本身就不太熟悉,那么我得 ...
- 第二十一节:Asp.Net Core MVC和WebApi路由规则的总结和对比
一. Core Mvc 1.传统路由 Core MVC中,默认会在 Startup类→Configure方法→UseMvc方法中,会有默认路由:routes.MapRoute("defaul ...
- [ExtJS5学习笔记]第二十一节 Extjs5中使用config配置给ext.widget或者create方法传递参数
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39252805 官方例子:http://docs.sencha.com/extjs/5. ...
- 第二十一节:Java语言基础-关键字,标识符,注释,常量和变量,运算符
Java语言基础-关键字,标识符,注解,常量和变量,运算符 class Demo { public static void main(String[] args){ System.out.printl ...
- php第二十一节课
AJAX <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...
- ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借
ASP.NET MVC深入浅出系列(持续更新) 一. ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态模 ...
随机推荐
- 索引-mysql
什么是索引 索引的四大作用 (参考百度百科:百度百科-索引) 索引的优缺点 索引分类 什么地方需要建索引 索引优化 什么是索引? 宏观来说,索引是一种检索工具,目录也是一种检索工具,但是两者是有区是别 ...
- Windows Service 学习系列(三)——循环引擎 ICycleEngine
摘要:转载:https://www.cnblogs.com/zhuweisky/archive/2009/09/01/1557792.html#undefined 1.缘起: 有些系统需要每隔一段时间 ...
- 在windows下远程访问linux桌面
一.安装xrdp工具: # yum install xrdp # yum install tigervnc-server # service xrdp start 以上三个命令执行完毕安装完 ...
- F. Multicolored Markers(数学思维)
思维:思维就是将大的矩形放在小矩形里面,让大矩形的宽和长尽量靠近. 很容易得到 (a+b)% i = 0 的话, 保证了大矩形的形成,同时里面表示了两种情况:1, a % i =0, b % i=0; ...
- tensorboard 可视化网络运行过程
在 tf.summary 里设置好要查看保存的参数后运行会生成 events.out.tfevents.{time}.{machine-name} 的文件,这个就是用 tensorboard 来查看的 ...
- SpringBoot开发案例之拦截器注入Bean
前言 由于业务需要,需要在拦截器中操作Redis缓存,按照 controller,service层配置发现无法注入,一直报空指针异常. 解决方案 @Configuration public class ...
- HTML页面全屏/退出全屏
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [Alpha阶段]第二次Scrum Meeting
Scrum Meeting博客目录 [Alpha阶段]第二次Scrum Meeting 基本信息 名称 时间 地点 时长 第二次Scrum Meeting 19/04/04 大运村寝室6楼 90min ...
- Binary Search(Java)(非递归)
public static int rank(int[] array, int k) { int front = 0, rear = array.length - 1; while(front < ...
- 解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度-美团)
还有其他的锁,如果想要了解,参考:JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁, 用synchronized实现ReentrantLock 美团面试题参考:使用synchronized ...