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:UsersWenDaoJunDocumentsVisual Studio 2015ProjectsJWellJWell.Cloud.UIResourcesTxt";
            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++)
                {
                    // 拼接数据
                    // 解析文本文件  ""号段"	"所属地区"	"号码类型"	"区号"" 
                    var strs = lines[i].Split('	');
                    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();
                // 拼接数据
                // 解析文本文件  ""号段"	"所属地区"	"号码类型"	"区号"" 
                var strs = lines[i].Split('	');
                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; });

        }
    }
原文地址:https://www.cnblogs.com/wendj/p/9015018.html