准备条件: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数据批量入库的更多相关文章

  1. discuz数据批量入库接口

    近期在做社区,首选discuz,数据需要用scrapy爬虫批量入库,就写了一个php入库接口. <?php define('PW', 'abc123456');//一定要修改 if($_REQU ...

  2. C# SqlBulkCopy类批量导入数据

    特别注意  sqlbulkcopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName); 插入的时候列的顺序可 ...

  3. SqlBulkCopy将DataTable中的数据批量插入数据库中

    #region 使用SqlBulkCopy将DataTable中的数据批量插入数据库中 /// <summary> /// 注意:DataTable中的列需要与数据库表中的列完全一致.// ...

  4. list转datatable,SqlBulkCopy将DataTable中的数据批量插入数据库

    /// <summary> /// 将泛类型集合List类转换成DataTable /// </summary> /// <param name="list&q ...

  5. DataTable数据批量写入数据库三种方法比较

    DataTable数据批量写入数据库三种方法比较 标签: it 分类: C#1)   insert循环插入:2)   sqldataadapter.update(dataset,tablename); ...

  6. 【hbase】——HBase 写优化之 BulkLoad 实现数据快速入库

    1.为何要 BulkLoad 导入?传统的 HTableOutputFormat 写 HBase 有什么问题? 我们先看下 HBase 的写流程: 通常 MapReduce 在写HBase时使用的是 ...

  7. 高并发简单解决方案————redis队列缓存+mysql 批量入库(ThinkPhP)

    问题分析 问题一:要求日志最好入库:但是,直接入库mysql确实扛不住,批量入库没有问题,done.[批量入库和直接入库性能差异] 问题二:批量入库就需要有高并发的消息队列,决定采用redis lis ...

  8. 转载:【高并发简单解决方案 | 靠谱崔小拽 】redis队列缓存 + mysql 批量入库 + php离线整合

    需求背景:有个调用统计日志存储和统计需求,要求存储到mysql中:存储数据高峰能达到日均千万,瓶颈在于直接入库并发太高,可能会把mysql干垮. 问题分析 思考:应用网站架构的衍化过程中,应用最新的框 ...

  9. C#中几种数据库的大数据批量插入

    C#语言中对SqlServer.Oracle.SQLite和MySql中的数据批量插入是支持的,不过Oracle需要使用Orace.DataAccess驱动. IProvider里有一个用于实现批量插 ...

随机推荐

  1. Linux下修改Oracle数据库字符集命令

    常见情形:从服务器备份Oracle数据库后再到本地机器上还原Oracle数据库的时候经常会碰见数据库字符编码不一致的情况,可以用以下命令来修改本地的Oracle数据库字符编码,然后顺利还原Oracle ...

  2. C++ Primer 有感(类)

    1.在类内部,声明成员函数时必需 的,而定义成员函数则是可选的.在类内部定义的函数默认为inline. 2.const成员函数不能改变其所操作的对象的数据成员.const必须同时出现在声明和定义中,若 ...

  3. leetcode 204题求素数个数

        Description: Count the number of prime numbers less than a non-negative number, n 提示晒数法: http:// ...

  4. How To Transact Move Order Using INV_PICK_WAVE_PICK_CONFIRM_PUB.Pick_Confirm API

    In this Document Goal   Solution   Sample Code:   Steps:   FAQ   References APPLIES TO: Oracle Inven ...

  5. 不要使用jQuery触发原生事件

    原文链接: DO NOT TRIGGER REAL EVENT NAMES WITH JQUERY! 原文日期: 2014年02月26日 翻译日期: 2014年03月2日 翻译人员: 铁锚 JavaS ...

  6. 用LED灯和按键来模拟工业自动化设备的运动控制

    开场白: 前面三节讲了独立按键控制跑马灯的各种状态,这一节我们要做一个机械手控制程序,这个机械手可以左右移动,最左边有一个开关感应器,最右边也有一个开关感应器.它也可以上下移动,最下面有一个开关感应器 ...

  7. 自定义view入门

    如何自定义控件主要分为以下几个步骤: 1.自定义属性的声明与获取 (1)分析需要的自定义属性 (2)在res/values/attrs.xml定义声明,如 <resources> < ...

  8. Android模拟器启动不了解决办法

    问题描述:Windows2008中的MyEclipse项目在Windows2003中运行时无法启动模拟器. 解决要点:启动模拟器管理工具,在启动中设置属性中不勾选默认尺寸显示. 系统错误如下: [20 ...

  9. Bloom filter 2

    1 Bloom filter 计算方法 如需要判断一个元素是不是在一个集合中,我们通常做法是把所有元素保存下来,然后通过比较知道它是不是在集合内,链表.树都是基于这种思路,当集合内元素个数的变大,我们 ...

  10. 【Django】 gunicorn部署纪要

    使用Gunicorn 来部署Django应用, 没有一步一步写怎么操作,简单记录下重要的点,方面以后查阅. 主要的方式还是Nginx反向代理到Gunicorn, Gunicorn wsgi来启动Dja ...