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里有一个用于实现批量插 ...
随机推荐
- 修改GDAL库支持RPC像方改正模型
最近在做基于RPC的像方改正模型,方便对数据进行测试,修改了GDAL库中的RPC纠正模型,使之可以支持RPC像方改正参数. 下面是RPC模型的公式,rn,cn为归一化之后的图像行列号坐标,PLH为归一 ...
- pig的cogroup详解
从实例出发 %default file test.txt A = load '$file' as (date, web, name, food); B = load '$file' as (date, ...
- webview与js交互
对于android初学者应该都了解webView这个组件.之前我也是对其进行了一些简单的了解,但是在一个项目中不得不用webview的时候,发现了webview的强大之处,今天就分享一下使用we ...
- listview优化(中)
1,对Imageview使用setTag()方法来解决图片错位问题,这个Tag中设置的是图片的url,然后在加载的时候取得这个url和要加载那position中的url对比,如果不相同就加载,相同就是 ...
- C#之委托和事件
我想,读者们可能看过一部电影叫<全民目击>,在电影中,富豪林泰婚期将至,准新娘却惨死地下停车场,林泰的富二代女儿林萌萌成为最大嫌疑人,林泰不惜重金聘请国内顶级律师周莉为女儿辩护,而公诉方却 ...
- 使用API获取(默认付款条件和到期日)
1. 目的:使用API取到应收事务处理的付款条件(实现标准功能的付款条件和到期日)2. 实现方法:调用 ARP_TRX_DEFAULTS_3.get_term_default获得付款条件 3.实现代码 ...
- nodejs书籍
http://product.dangdang.com/23371791.html#catalog https://www.byvoid.com/project/node http://www.ama ...
- Android 几种网络请求的区别与联系
HttpUrlConnection 最开始学android的时候用的网络请求是HttpUrlConnection,当时很多东西还不知道,但是在android 2.2及以下版本中HttpUrlConne ...
- Spring--ClassPathResource
/* * 用一个给定的类加载器或者给定的类来加载资源 */ public class ClassPathResource extends AbstractFileResolvingResource { ...
- 收集一些dos网络配置命令,从新获取ip刷新dns
今天台式机插着无线网卡连接学校无线网,结果就要登录了,完后ip地址固定半天,换了mac地址重新分配还是不能改,ping了主机也不通,我想可能是dns没有刷新.现在收集几个dos命令用来配置网络: 1. ...