C# SqlBulkCopy数据批量入库
准备条件:20万+数据
界面设计使用的WPF。
没有对比就没有伤害,以下是我两种方式导入数据案例。

运行 结果对比:
首先使用一般sql语句导入,因为时间原因,我就没有等待程序执行完,但是我记录了大约需要多少时间,以及执行了多少时间。
导入数据共计:258113条,执行了38秒,已经入库了6971条,大约还需要1429秒。(不去考虑电脑配置,界面数据加载耗时等因素)

接下来我们看看同样的数据量 SqlBulkCopy效果如何:

当我注释代码中使用异步操作,当然,界面会出现假死状态。再来看看运行结果。


解析数据时间明显减少。
以下是这个测试工具的全部代码:
/// <summary>
/// BatchImportForm.xaml 的交互逻辑
/// </summary>
public partial class BatchImportForm : Window
{
private static readonly string ConnStr = ConfigurationManager.ConnectionStrings["myconnStr"].ConnectionString;
public BatchImportForm()
{
InitializeComponent();
} private void BtnQueryImport_Click(object sender, RoutedEventArgs e)
{
var filePath = GetFilePath();
if (!string.IsNullOrEmpty(filePath))
{
// 防止界面假死状态
Task task = Task.Factory.StartNew(() =>
{
SqlWork(filePath);
});
}
} private string GetFilePath()
{
// 读取文本文件
OpenFileDialog ofd = new OpenFileDialog();
ofd.InitialDirectory = System.Environment.CurrentDirectory+ "\\Resources\\Txt"; // @"C:\Users\WenDaoJun\Documents\Visual Studio 2015\Projects\JWell\JWell.Cloud.UI\Resources\Txt";
ofd.Title = "读取文件";
ofd.FileName = "";
ofd.RestoreDirectory = true;
ofd.Filter = "所有文件(*.*)|*.*|文本文件(*.txt)|*.txt";
ofd.ValidateNames = true;
ofd.CheckFileExists = true;
ofd.CheckPathExists = true;
string strName = string.Empty;
if (ofd.ShowDialog() == true)
{
strName = ofd.FileName;
}
if (strName == "")
{
MessageBox.Show("没有选择文件!");
return null;
}
return strName;
} private void BtnQueryImportTwo_Click(object sender, RoutedEventArgs e)
{
string filePath = GetFilePath();
//if (!string.IsNullOrEmpty(filePath))
//{
// Task task = Task.Factory.StartNew(() =>
// {
// SqlBulkWord(filePath);
// }); //}
SqlBulkWord(filePath);
} /// <summary>
/// 第一种方法
/// </summary>
/// <param name="fuillPath"></param>
private void SqlWork(string fuillPath)
{
var lines = File.ReadAllLines(fuillPath, Encoding.Default);
// 异步给控件赋值
this.Dispatcher.Invoke(() => { this.JingDuOn.Maximum = lines.Length; });
this.Dispatcher.Invoke(() => { this.LblRuKuOne.Content = lines.Length; });
using (SqlConnection conn = new SqlConnection(ConnStr))
{
conn.Open();
var t1 = DateTime.Now;
for (int i = ; i < lines.Length; i++)
{
// 拼接数据
// 解析文本文件 "\"号段\"\t\"所属地区\"\t\"号码类型\"\t\"区号\""
var strs = lines[i].Split('\t');
var telNumber = strs[].Trim('"');
var telArea = strs[].Trim('"');
var telType = strs[].Trim('"');
var telAreaCode = strs[].Trim('"');
// 入库
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = @"insert into TelNum(TelNumber,TelType,TelArea,TelAreaCode) values(@TelNumber,@TelType,@TelArea,@TelAreaCode)";
cmd.Parameters.Add(new SqlParameter("@TelNumber", telNumber));
cmd.Parameters.Add(new SqlParameter("@TelType", telArea));
cmd.Parameters.Add(new SqlParameter("@TelArea", telType));
cmd.Parameters.Add(new SqlParameter("@TelAreaCode", telAreaCode));
cmd.ExecuteNonQuery();
//异步委托
this.JingDuOn.Dispatcher.Invoke(() => { this.JingDuOn.Value += ; });
this.LblJinDuOne.Dispatcher.Invoke(() => { this.LblJinDuOne.Content = i; });
}
var t2 = DateTime.Now;
var tsp = t2 - t1;
// 异步给控件赋值
this.LblHaoShiOne.Dispatcher.Invoke(() => { this.LblHaoShiOne.Content = tsp.TotalSeconds; });
this.LblZongHaoShiOne.Dispatcher.Invoke(() => { this.LblZongHaoShiOne.Content = $"倒计时{(tsp.TotalSeconds * lines.Length / (i + 1))}秒完成。"; });
} }
} /// <summary>
/// 第二种方法
/// </summary>
/// <param name="filePath"></param>
private void SqlBulkWord(string filePath)
{
var lines = File.ReadAllLines(filePath, Encoding.Default);
this.Dispatcher.Invoke(() => { this.JingDuTwo.Maximum = lines.Length; });
this.Dispatcher.Invoke(() => { this.LblRuKuTwo.Content = lines.Length; });
var t1 = DateTime.Now; // 创建入库需要的数据源 DataTable
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("TelNumber", typeof(string)));
dt.Columns.Add(new DataColumn("TelType", typeof(string)));
dt.Columns.Add(new DataColumn("TelArea", typeof(string)));
dt.Columns.Add(new DataColumn("TelAreaCode", typeof(string))); for (int i = ; i < lines.Length; i++)
{
var row = dt.NewRow();
// 拼接数据
// 解析文本文件 "\"号段\"\t\"所属地区\"\t\"号码类型\"\t\"区号\""
var strs = lines[i].Split('\t');
row["TelNumber"] = strs[].Trim('"');
row["TelType"] = strs[].Trim('"');
row["TelArea"] = strs[].Trim('"');
row["TelAreaCode"] = strs[].Trim('"');
dt.Rows.Add(row); this.JingDuTwo.Dispatcher.Invoke(() => { this.JingDuTwo.Value += ; });
this.LblJinDuTwo.Dispatcher.Invoke(() => { this.LblJinDuTwo.Content = i; }); }
var t2 = DateTime.Now;
var tsp = t2 - t1;
this.LblHaoShiTwo.Dispatcher.Invoke(() => { this.LblHaoShiTwo.Content = tsp.TotalSeconds; }); // 入库计时
var sw = new Stopwatch();
sw.Start();
using (SqlBulkCopy sbk = new SqlBulkCopy(ConnStr))
{
//表名
sbk.DestinationTableName = "TelNum";
//DataTable中的列名和数据库中列名对应
sbk.ColumnMappings.Add("TelNumber", "TelNumber");
sbk.ColumnMappings.Add("TelType", "TelType");
sbk.ColumnMappings.Add("TelArea", "TelArea");
sbk.ColumnMappings.Add("TelAreaCode", "TelAreaCode");
sbk.WriteToServer(dt);
}
sw.Stop(); this.LblZongHaoShiTwo.Dispatcher.Invoke(() => { this.LblZongHaoShiTwo.Content=sw.Elapsed.TotalSeconds; }); }
}
C# SqlBulkCopy数据批量入库的更多相关文章
- discuz数据批量入库接口
近期在做社区,首选discuz,数据需要用scrapy爬虫批量入库,就写了一个php入库接口. <?php define('PW', 'abc123456');//一定要修改 if($_REQU ...
- C# SqlBulkCopy类批量导入数据
特别注意 sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName); 插入的时候列的顺序可 ...
- SqlBulkCopy将DataTable中的数据批量插入数据库中
#region 使用SqlBulkCopy将DataTable中的数据批量插入数据库中 /// <summary> /// 注意:DataTable中的列需要与数据库表中的列完全一致.// ...
- list转datatable,SqlBulkCopy将DataTable中的数据批量插入数据库
/// <summary> /// 将泛类型集合List类转换成DataTable /// </summary> /// <param name="list&q ...
- DataTable数据批量写入数据库三种方法比较
DataTable数据批量写入数据库三种方法比较 标签: it 分类: C#1) insert循环插入:2) sqldataadapter.update(dataset,tablename); ...
- 【hbase】——HBase 写优化之 BulkLoad 实现数据快速入库
1.为何要 BulkLoad 导入?传统的 HTableOutputFormat 写 HBase 有什么问题? 我们先看下 HBase 的写流程: 通常 MapReduce 在写HBase时使用的是 ...
- 高并发简单解决方案————redis队列缓存+mysql 批量入库(ThinkPhP)
问题分析 问题一:要求日志最好入库:但是,直接入库mysql确实扛不住,批量入库没有问题,done.[批量入库和直接入库性能差异] 问题二:批量入库就需要有高并发的消息队列,决定采用redis lis ...
- 转载:【高并发简单解决方案 | 靠谱崔小拽 】redis队列缓存 + mysql 批量入库 + php离线整合
需求背景:有个调用统计日志存储和统计需求,要求存储到mysql中:存储数据高峰能达到日均千万,瓶颈在于直接入库并发太高,可能会把mysql干垮. 问题分析 思考:应用网站架构的衍化过程中,应用最新的框 ...
- C#中几种数据库的大数据批量插入
C#语言中对SqlServer.Oracle.SQLite和MySql中的数据批量插入是支持的,不过Oracle需要使用Orace.DataAccess驱动. IProvider里有一个用于实现批量插 ...
随机推荐
- Device Tree Usage(理解DTS文件语法)
Basic Data Format The device tree is a simple tree structure of nodes and properties. Properties are ...
- C语言中字符串常用函数--strcat,strcpy
strcpy 原型声明:extern char *strcpy(char* dest, const char *src); 头文件:#include <string.h> 功能:把从src ...
- Java中回调函数编写
package XXX.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStr ...
- iOS开发支付集成之微信支付
这一篇是<iOS开发之支付>这一部分的继支付宝支付集成,银联支付集成第三篇,微信支付.在集成的时候建议都要去下载最新版的SDK,因为我知道的前不久支付宝,银联都更新了一次,微信的不太清楚更 ...
- 重构前VS重构后效果对比
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42554641 学习重构已经一个多月了,虽然不能让代码特别的 ...
- 【翻译】Ext JS——高效的编码风格指南
原文:ExtJS - Efficient coding style guide 作者:Raja 切勿使用"new"关键字:在Ext JS中,使用"new"关键字 ...
- RabbitMQ安装使用详解
1.下载相应的版本安装:http://www.rabbitmq.com/download.htmleg:http://www.rabbitmq.com/releases/rabbitmq-server ...
- 【翻译】Siesta事件记录器入门
原文:Getting started with the Siesta event recorder 作者:Mats Bryntse 随着事件记录器功能的发布越来越近,我们准备了一下入门指南,向大家展示 ...
- mongodb系列之--mongodb 主从配置与说明
一.为什么要配置mongodb的主从: 1.做主从,可以说是做数据的备份,有利于故障的恢复 2.做主从,可以做到读写分离,主节点负责写操作,从节点负责读操作,这样就把读写压力分开,保证系统的稳定性. ...
- rails无法使用页面缓存的解决办法
书上云在config/envirionments/development.rb中开启了缓存机制后,我们即可以使用缓存鸟: config.action_controller.perform_cach ...