讀者問題與解答 - 使用 SqlBulkCopy 大量複製文字檔之 C# 程式碼

摘要:讀者問題與解答 - 使用 SqlBulkCopy 大量複製文字檔之 C# 程式碼

我們在之前的一篇文章(http://blog.xuite.net/alwaysfuturevision/liminzhang/8587975?st=c&re=list&p=1&w=487124)提到如何使用 SqlBulkCopy 物件來大量複製文字檔,當時所使用的程式語言是 Visual Basic 2005,有讀者希望提供 Visual C# 2005 的程式碼。在此茲將 Visual C# 2005  的程式碼列示如下,請自行參考之: 

// 匯入命名空間。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.VisualBasic.FileIO;

namespace VC
測試專案
{
    public partial class Form4 : Form
    {
        public Form4()
        {
            InitializeComponent();
        }

        private string[] currentRow;
        private int myRowCount = 1;
        private int myBatchCount = 1;
        private long myCopiedRows = 0;
        private long countStart;

        //
建立「章立民研究室」資料表,此處是當作一個中介資料表來使用。
        private DataTable myTable = new DataTable("章立民工作室");

        private void btnGoBulkCopy_Click(object sender, EventArgs e)
        {
            this.btnGoBulkCopy.Enabled = false;

            //
建立「員工編號」欄位。
            DataColumn colEmployeeId =
                myTable.Columns.Add("
員工編號", Type.GetType("System.Int32"));

            //
建立「身份證字號」欄位。
            myTable.Columns.Add("身份證字號", Type.GetType("System.String"));
            myTable.Columns["
身份證字號"].MaxLength = 10;
            myTable.Columns["
身份證字號"].AllowDBNull = false;

            //
建立「姓名」欄位。
            myTable.Columns.Add("姓名", Type.GetType("System.String"));
            myTable.Columns["
姓名"].MaxLength = 12;

            //
建立「性別」欄位。
            myTable.Columns.Add("性別", Type.GetType("System.String"));
            // myTable.Columns["
性別"].MaxLength = 1;

            // 建立「地址」欄位。
            myTable.Columns.Add("地址", Type.GetType("System.String"));
            myTable.Columns["
地址"].MaxLength = 41;

            //
建立「郵遞區號」欄位。
            myTable.Columns.Add("郵遞區號", Type.GetType("System.String"));
            myTable.Columns["
郵遞區號"].MaxLength = 5;

            //
建立「出生日期」欄位。
            myTable.Columns.Add("出生日期", Type.GetType("System.DateTime"));

            //
建立「婚姻狀況」欄位。
            myTable.Columns.Add("婚姻狀況", Type.GetType("System.String"));

            //
建立「僱用日期」欄位。
            myTable.Columns.Add("僱用日期", Type.GetType("System.DateTime"));

            //
建立「起薪」欄位。
            myTable.Columns.Add("起薪", Type.GetType("System.Double"));

            //
建立「目前薪資」欄位。
            myTable.Columns.Add("目前薪資", Type.GetType("System.Double"));

            //
建立「加薪日期」欄位。
            myTable.Columns.Add("加薪日期", Type.GetType("System.DateTime"));

            //
建立「部門」欄位。
            myTable.Columns.Add("部門", Type.GetType("System.String"));
            myTable.Columns["
部門"].MaxLength = 10;

            using(TextFieldParser myReader = new TextFieldParser(@"Text
章立民工作室.txt"))
            {
                //
表示檔案內容是字元分隔。
                myReader.TextFieldType = FieldType.Delimited;

                //
定義文字檔的字元分隔符號。
                myReader.Delimiters = new string[] {","};

                //
循環處理文字檔中所有資料列的所有欄位。
                while(!myReader.EndOfData)
                {
                    try
                    {
                        currentRow = myReader.ReadFields();

                        //
略過標題列
                        if(myRowCount > 1)

                       {
                            myTable.Rows.Add(currentRow);
                        }
                    }
                    catch(MalformedLineException ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }

                    myRowCount += 1;
                    this.lblBeingCopyedTextRows.Text = myTable.Rows.Count.ToString();
                    this.lblBeingCopyedTextRows.Refresh();

                    if(myTable.Rows.Count == 50000)
                    {
                        try
                        {
                            GoBulkCopy();
                        }
                        catch(Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                            return;
                        }

                        //
清空資料表。
                        myTable.Rows.Clear();
                        myBatchCount += 1;
                    }
                }

                //
複製最後一批不足50000 筆的資料記錄。
                if(myTable.Rows.Count > 0)
                {
                    GoBulkCopy();
                }
            }

            this.lblBeingCopyedTextRows.Text = myTable.Rows.Count.ToString();
            this.lblTextFileRowCount.Text =
              "
來源文字檔的資料筆數:" + (myRowCount - 2).ToString();
            this.btnGoBulkCopy.Enabled = true;
        }

        private void GoBulkCopy()
        {
            //
利用SqlConnectionStringBuilder 物件來構建連接字串。
            // 由於本範例是在同一個SQL Server 資料庫的不同資料表之間進行大量複
            // 製作業,因此連接至來源資料庫與連接至目標伺服器的連接字串是相同的。
            SqlConnectionStringBuilder sqlconStringBuilder =
              new SqlConnectionStringBuilder();

            sqlconStringBuilder.DataSource = @"(local)SQLExpress";
            sqlconStringBuilder.InitialCatalog = "
北風貿易";
            sqlconStringBuilder.IntegratedSecurity = true;

            //
建立連結至目標SQL Server 資料庫的連接。
            using(SqlConnection con_bulkcopy =
              new SqlConnection(sqlconStringBuilder.ConnectionString))
            {
                //
開啟連接至目標SQL Server 的連接。
                con_bulkcopy.Open();

                SqlCommand cmdRowCount = new SqlCommand(
                  "SELECT COUNT(*) FROM dbo.Bulk_Target_
章立民工作室;",
                  con_bulkcopy);

                if(myBatchCount == 1)
                {
                    //
計算出目標資料表在執行大量複製作業前有多少筆資料記錄。
                    countStart =
                      System.Convert.ToInt32(cmdRowCount.ExecuteScalar());
                    this.lblRowsCountBeforeBulkCopy.Text =
                      "
目標資料表在大量複製前擁有的資料筆數= " +
                      countStart.ToString();
                    this.lblRowsCountBeforeBulkCopy.Refresh();
                }

                //
建立一個SqlBulkCopy 物件以便執行大量複製作業。
                using(SqlBulkCopy bcp = new SqlBulkCopy(con_bulkcopy))
                {
                    //
指定目標資料表的名稱。
                    bcp.DestinationTableName = "dbo.Bulk_Target_章立民工作室";

                    //
如果來源資料表與目標資料表的各個欄位順序沒有完全對應,
                    // 必須在此設定來源欄位與目標欄位的對應關係。

                    // 將來源資料寫入目標資料表。
                    bcp.WriteToServer(myTable);
                }

                //
最後再計算出大量複製了多少筆資料記錄。
                long countEnd =
                  System.Convert.ToInt32(cmdRowCount.ExecuteScalar());

                //
計算出累計複製筆數。
                myCopiedRows = countEnd - countStart;

                //
顯示出批次與大量複製累計筆數。
                this.DataGridView1.Rows.Add(
                  new string[] {
                  Convert.ToString(myBatchCount), Convert.ToString(myCopiedRows)});
                this.DataGridView1.Refresh();
            }
        }
    }
}

章立民研究室 2006/12/21