準備條件:20萬+數據sql
界面設計使用的WPF。數據庫
沒有對比就沒有傷害,如下是我兩種方式導入數據案例。app
運行 結果對比:異步
首先使用通常sql語句導入,由於時間緣由,我就沒有等待程序執行完,可是我記錄了大約須要多少時間,以及執行了多少時間。
導入數據共計:258113條,執行了38秒,已經入庫了6971條,大約還須要1429秒。(不去考慮電腦配置,界面數據加載耗時等因素)工具
接下來咱們看看一樣的數據量 SqlBulkCopy效果如何:測試
當我註釋代碼中使用異步操做,固然,界面會出現假死狀態。再來看看運行結果。ui
解析數據時間明顯減小。this
如下是這個測試工具的所有代碼:spa
/// <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 = 0; i < lines.Length; i++) { // 拼接數據 // 解析文本文件 "\"號段\"\t\"所屬地區\"\t\"號碼類型\"\t\"區號\"" var strs = lines[i].Split('\t'); var telNumber = strs[0].Trim('"'); var telArea = strs[1].Trim('"'); var telType = strs[2].Trim('"'); var telAreaCode = strs[3].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 += 1; }); 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 = 0; i < lines.Length; i++) { var row = dt.NewRow(); // 拼接數據 // 解析文本文件 "\"號段\"\t\"所屬地區\"\t\"號碼類型\"\t\"區號\"" var strs = lines[i].Split('\t'); row["TelNumber"] = strs[0].Trim('"'); row["TelType"] = strs[1].Trim('"'); row["TelArea"] = strs[2].Trim('"'); row["TelAreaCode"] = strs[3].Trim('"'); dt.Rows.Add(row); this.JingDuTwo.Dispatcher.Invoke(() => { this.JingDuTwo.Value += 1; }); 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; }); } }