none
將 txt 檔資料匯入Access RRS feed

  • 一般討論

  • 客戶要求要把原本的 VB6.0 程式,改成C#,

    舊版: VB6.0、Access2003
    新版: Visual Studio 2010(C#)、Access2010 

    有隻程式是要把 txt 檔的資料匯入Access,大約有5千多筆資料,我執行舊版的,3秒內就可以處理完,

    我用C#寫,同樣的txt檔,大概2分鐘才處理完,客戶那邊說年代久遠,找不到原始碼了,所以我也看不到原本的程式是怎麼處理的,

    以下是我的程式,請教各位大大,我要怎麼改,才能在3秒內處理完呢? ^^

            private void btnStart_Click(object sender, EventArgs e)
            {
                string strConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Persist Security Info=True", lblDBFilePath.Text);
                OleDbConnection odcConnection = new OleDbConnection(strConnectionString);
                OleDbCommand odcCommand = new OleDbCommand();
                odcCommand.Connection = odcConnection;
                odcConnection.Open();
                OleDbTransaction odTran = odcConnection.BeginTransaction();
                odcCommand.Transaction = odTran;
               
                try
                {
                    if (MessageBox.Show("確定匯入?", "匯入確認", MessageBoxButtons.OKCancel) == DialogResult.OK)
                    {
                        string strNow = DateTime.Now.ToString();
                       
                        this.Cursor = Cursors.WaitCursor;

                        int intLine = 0;
                        int intSuccess = 0;
                        int intFail = 0;
                        string strItemCode = "";
                        string strItemName = "";
                        bool IsSuccess = false;
                        DataTable dt = new DataTable();
                        dt.Columns.Add("ItemCode", Type.GetType("System.String"));
                        dt.Columns.Add("ItemName", Type.GetType("System.String"));
                        dt.Columns.Add("Remark", Type.GetType("System.String"));
                        dt.Columns.Add("CreateTime", Type.GetType("System.String"));
                        dt.Columns.Add("CreateEmployeeCode", Type.GetType("System.String"));
                        dt.Columns.Add("UpdateTime", Type.GetType("System.String"));
                        dt.Columns.Add("UpdateEmployeeCode", Type.GetType("System.String"));
                        dt.Columns.Add("Status", Type.GetType("System.String"));

                        IEnumerable<string> lines_A = File.ReadLines(strItemCodeFile, System.Text.Encoding.Default);
                        foreach (var line in lines_A)
                        {
                            intLine++;
                            IsSuccess = true;

                            strItemCode = line.Substring(0, 7).Trim();
                            if (strItemCode.Length != 7)
                            {
                                IsSuccess = false;
                            }

                            strItemName = line.Substring(8, 40).Trim();
                            if (strItemName == "")
                            {
                                IsSuccess = false;
                            }

                            if (IsSuccess)
                            {
                                //判斷資料是否已經存在
                                if (dt.Select("ItemCode='" + strItemCode + "'").Length > 0)
                                {
                                    IsSuccess = false;
                                }
                            }

                            DataRow drNewRow = dt.NewRow();
                            drNewRow["ItemCode"] = strItemCode;
                            drNewRow["ItemName"] = strItemName;
                            drNewRow["Remark"] = "";
                            drNewRow["CreateTime"] = DateTime.Now.ToString();
                            drNewRow["CreateEmployeeCode"] = frmMenu_Ref.lblEmployeeCode.Text;
                            drNewRow["UpdateTime"] = DateTime.Now.ToString();
                            drNewRow["UpdateEmployeeCode"] = frmMenu_Ref.lblEmployeeCode.Text;
                           
                            if (IsSuccess)
                            {
                                drNewRow["Status"] = "1";
                            }
                            else
                            {
                                drNewRow["Status"] = "0";
                            }

                            dt.Rows.Add(drNewRow);
                        }

                        if (intLine < 1)
                        {
                            MessageBox.Show("來源檔無資料!");
                        }
                        else
                        {
                            string strSql = " Delete From ItemData ";
                            odcCommand.CommandText = strSql;
                            odcCommand.ExecuteNonQuery();

                            for (int i = 0; i < dt.Rows.Count;i++ )
                            {
                                if (dt.Rows[i]["Status"].ToString() == "1")
                                {
                                    strSql = " Insert Into ItemData(ItemCode,ItemName,Remark,CreateTime,CreateEmployeeCode,UpdateTime,UpdateEmployeeCode,Status) "
                                             + " Values(?,?,?,?,?,?,?,?) ";

                                    odcCommand.CommandText = strSql;

                                    odcCommand.Parameters.Clear();
                                    odcCommand.Parameters.Add(new OleDbParameter("?", dt.Rows[i]["ItemCode"].ToString()));
                                    odcCommand.Parameters.Add(new OleDbParameter("?", dt.Rows[i]["ItemName"].ToString()));
                                    odcCommand.Parameters.Add(new OleDbParameter("?", dt.Rows[i]["Remark"].ToString()));
                                    odcCommand.Parameters.Add(new OleDbParameter("?", DateTime.Now.ToString()));
                                    odcCommand.Parameters.Add(new OleDbParameter("?", dt.Rows[i]["CreateEmployeeCode"].ToString()));
                                    odcCommand.Parameters.Add(new OleDbParameter("?", DateTime.Now.ToString()));
                                    odcCommand.Parameters.Add(new OleDbParameter("?", dt.Rows[i]["UpdateEmployeeCode"].ToString()));
                                    odcCommand.Parameters.Add(new OleDbParameter("?", dt.Rows[i]["Status"].ToString()));

                                    if (odcCommand.ExecuteNonQuery() != 1)
                                    {
                                        MessageBox.Show("匯入失敗:第" + (i+1).ToString() + "筆錯誤!");

                                        return;
                                    }
                                    else
                                    {
                                        intSuccess++;
                                    }
                                }
                                else
                                {
                                    intFail++;
                                }
                            }

                            odTran.Commit();
                            MessageBox.Show("商品代碼轉入完畢!\n成功筆數: " + intSuccess.ToString() + " 筆\n失敗筆數:" + intFail.ToString() +" 筆");
                            MessageBox.Show("開始:" + strNow + ",結束:" + DateTime.Now.ToString());
                        }
                    }
                }
                catch (Exception ex)
                {
                    odTran.Rollback();
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    odcCommand.Dispose();
                    odcConnection.Close();

                    this.Cursor = Cursors.Arrow;
                }
            }

    2013年10月11日 上午 04:27

所有回覆

  • (1) 先量測問題是出在將 txt 檔讀進來的時間過長, 還是 Insert 進 Access 的時間過長.

    (2) DbDataAdapter.Update 仍然是每個列資料個別更新, 並不是當作批次程序


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 <br/> <a target="_blank" href="http://www.bplan.com.tw/chunfeng/front/bin/ptlist.phtml?Category=103591"><img border="0" src="http://files.dotblogs.com.tw/billchung/1007/20107414497912.gif" width="200" height="67"></a>

    2013年10月11日 上午 05:43
    版主
  • //判斷資料是否重複
    //if (dt.Select("ItemCode='" + strItemCode + "'").Length > 0)
    //{
               //IsSuccess = false;
    //}

    發現把上面那段拿掉後,整個處理時間就變為20幾秒,這20幾秒都是花在Insert 進 Access,

    改用DbDataAdapter.Update也是一樣,請問還有什麼方法能夠讓它在3秒內處理完嗎?謝謝~ ^^

    2013年10月11日 上午 07:56
  • 是否每 50 or 100筆... 才 insert 一併insert!

    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2013年10月11日 上午 08:04
  • 我沒實際試過, 不過提另一個想法, 你可以試試看.

    不要用 DataTable 來暫存讀進來的資料, 改用 List<T>, 減少型別轉換也許有機會.

    然後 Parameter 用替換的, 不要每次都產生新的執行個體.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 <br/> <a target="_blank" href="http://www.bplan.com.tw/chunfeng/front/bin/ptlist.phtml?Category=103591"><img border="0" src="http://files.dotblogs.com.tw/billchung/1007/20107414497912.gif" width="200" height="67"></a>

    2013年10月11日 上午 08:16
    版主
  • 如果是符合資料庫格式的 .txt ,可以參考這篇:

    In 子句的使用範例


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2013年10月11日 下午 01:33
  • 2013年10月12日 上午 04:47
  • 你貼的連結就是 In 子句。如果你有看過 oledb 的線上手冊,轉貼如下:


    IN 子句

    Microsoft Jet 資料庫引擎可以連接到的外部資料庫中定義資料表,例如 dBASE 或 Paradox 資料庫或外部
    Microsoft Jet 資料庫。


    語法

    指定目的地資料表:

    [SELECT | INSERT] INTO destination IN
        {path
    | ["path" "type"] | ["" [type; DATABASE =
    path]]}

    指定資料來源資料表:

    FROM tableexpression IN
        {path |
    ["path" "type"] | ["" [type; DATABASE = path]]}

    一個 SELECT 陳述式包含一個 IN 子句,可分為以下幾個部份:

    部份 敘述
    destination 將資料插入其中的外部資料表之名稱。
    tableexpression 從其中擷取資料的一個或多個資料表之名稱。 此引數可為單一資料表名稱、一個已儲存的查詢,或由 INNER JOINLEFT
    JOIN
    RIGHT JOIN 合成的結果。
    Path 包含了 table 的目錄或檔案的整個路徑。
    type 用以建立 table 的資料庫類型之名稱,如果資料庫不為 Microsoft Jet 資料庫 (例如 dBASE
    III、dBASE IV、Paradox 3.x、或Paradox 4.x)。


    註解

    您可以使用 IN 子句一次連接一個外部資料庫

    在某些狀況之中,path 引數可參照至包含資料庫檔案的目錄。 例如,當使用 dBASE、FoxPro 或 Paradox
    資料庫資料表,path 引數將指定包含 .dbf 或 .db 檔案的目錄。 由 destination
    tableexpression 引數可得到資料表檔案的名稱。

    指定非 Microsoft Jet 資料庫,名稱後面需附加分號 (;),並且將它包含在單引號 (' ') 或 (" ") 雙引號之中。 例如 'dBASE
    IV;' 或 "dBASE IV;",以上兩種寫法皆可接受。

    您亦可以使用 DATABASE 保留字指定外部資料庫。 例如,以下範例為指定相同的資料表:

    ... FROM Table IN "" [dBASE IV; DATABASE=C:\DBASE\DATA\SALES;];

    ... FROM Table IN "C:\DBASE\DATA\SALES" "dBASE IV;"



    備註

    為了改善執行效能及易於使用,請使用連結資料表而非 IN。

    在一個運算式之中,您亦可以使用 IN 保留字為比較運算子。
    若需更多資訊,請參閱 In運算子。





    請參閱
    FROM 子句 (Microsoft Jet SQL) SELECT 陳述式 (Microsoft Jet
    SQL)
    INNER JOIN 運算 (Microsoft Jet
    SQL)
    SELECT...INTO 陳述式 (Microsoft Jet
    SQL)
    INSERT INTO 陳述式 (Microsoft Jet
    SQL)
    SQL 聚合函數
    (SQL)
    LEFT JOIN 和 RIGHT JOIN 運算
    (Microsoft Jet SQL)


    範例

    IN 子句範例


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2013年10月12日 上午 09:22