准备条件: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. WebLogic重启

     1,用户名密码登录. 2,切换到weblogic的bin目录下  cd bea/user_projects/domains/base_domain/bin/ 3,先停止服务器  ./stopWe ...

  2. C++ Primer 有感(面向对象编程)

    1.除了构造函数之外,任意非static成员函数都可以是虚函数.保留字virtual只在类内部的成员函数声明处出现,不能用在类定义体外部出现的函数定义上. 2.派生类只能通过派生类对象访问其基类的pr ...

  3. 使用go reflect实现一套简易的rpc框架

    go jsonrpc 在实际项目中,我们经常会碰到服务之间交互的情况,如何方便的与远端服务进行交互,就是一个需要我们考虑的问题. 通常,我们可以采用restful的编程方式,各个服务提供相应的web接 ...

  4. 小强的HTML5移动开发之路(11)——链接,图片,表格,框架

    来自:http://blog.csdn.net/dawanganban/article/details/18098193 一.HTML是什么? HTML(hypertext mark-uplangua ...

  5. 认证模式之Digest模式

    TTP协议规范的另一种认证模式是Digest模式,在HTTP1.1时被提出来,它主要是为了解决Basic模式安全问题,用于替代原来的Basic认证模式,Digest认证也是采用challenge/re ...

  6. 学习pthreads,使用互斥量进行同步

    在进行多线程编程时,我们总会遇到全局变量和数据结构的问题,这是多线程之间进行通信的问题.如果多个线程同时读写一个全局变量,那么会造成竞争或者出错.为了解决这一问题,我们需要对全局数据进行,使用互斥量实 ...

  7. Material Design之RecyclerView的使用(一)

    Android 5.0开始就推荐使用Material Design这个设计语言,本文开始就逐一讲解Material Design中控件的使用.本章主要讲解RecyclerView,期中会带有ToolB ...

  8. Leetcode_122_Best Time to Buy and Sell Stock II

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/43155725 Say you have an array ...

  9. OpenCV由汉字生成图片(透明)----可以对抗论文查重!!!

    今天听说很多同志们写毕业论文重复率过高的问题,大牛说用图片代替字就行了,我就想用OpenCV实现一下看看能不能搞,果不其然还是可以的!!!主要的难点在于普通格式的图片背景不透明,需要使用背景透明的pn ...

  10. Spring--ApplicationContext

    //中心接口,给应用提供配置信息 public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory ...