Excel格式超大數據導入數據庫方案淺談

原創文章, 寫文章不易,轉載請標明!

最近工作需要用到EXCEL對數據庫進行導入數據,好久沒更新博客了,所以就來寫一寫最近的工作任務EXCEL數據讀取,導入數據庫的幾種方式。

  項目中原本使用的導入方式是使用NPOI導入(這個會在後面的文章介紹它的使用方法),這種方法的優點暫時沒發現什麼太好的地方,算是中規中矩的導入方式,速度不算太快,編寫方式也不算簡單。缺點呢就是對於導入EXCEL的行數超過65535行時,提示內存溢出,或者多個工作頁中的總行數超過65535也不行,但項目中需要用到接近五十萬行的數據導入,經過不斷的尋找,最終考慮使用ODP.NET訪問數據庫,這是oracle提供的數據庫訪問類庫,使用這個類庫,無需安裝oracle的客戶端,就可以訪問,導入速度奇快無比,三十萬條數據,導入僅需不到兩分鐘,這個速度還取決於你的服務器速度,我們導入需要用到的dll腳本爲Oracle.DataAccess.dll,可以訪問oralce官網下載(需要註冊賬號登陸後才能允許下載),也可以在此處下載https://download.csdn.net/download/weixin_34024244/10646267(版本可能不同),也可以在vs中直接添加(項目中的引用,右鍵-管理NUGET程序包-搜索oracle-對應圖片中的包安裝之後就會添加oracle.dataaccess.dll)

 

圖片

導入首先是讀取EXCEL的方法,這裏將excel轉成datatable格式代碼如下

/// <summary>
        /// 將EXCEL轉換成datatable格式的方法(使用此方法時,excel列的格式最好改爲文本,否則可能會出現爲0的現象)
        /// </summary>
        /// <param name="Path">文件的路徑</param>
        /// <returns></returns>
        public DataTable GetExcel(string Path)
        {
            Base.Logger.Info("GetExcel開始");
            string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + Path + ";" + "Extended Properties='Excel 8.0;HDR=YES;IMEX=1';";
            OleDbConnection conn = new OleDbConnection(strConn);
            OleDbDataAdapter myCommand = null;
            DataTable dt = new DataTable();
            int result = 1;
            try
            {
                conn.Open();
                DataTable dtName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" });
                string strExcel = "Select * from [" + dtName.Rows[0]["TABLE_NAME"].ToString() + "]";
                myCommand = new OleDbDataAdapter(strExcel, strConn);
                myCommand.Fill(dt);
                conn.Close();
            }
            catch (Exception ex)
            {
                result = 2;
                Base.Logger.Error("GetExcel的" + ex.ToString());
                throw ex;
            }
            finally
            {
                conn.Close();
            }
            if (result == 2) return null;
            else return dt;
        }

上面這種方法需要注意幾個問題,path爲你的excel的路徑,Base.Logger.Error是記日誌的方法,可以刪去。使用此方法你的電腦本地必須安裝office,並且對於excel中的純數字,EXCEL導入格式建議轉成純文本,否則導入的時候很可能對應數字列被轉換成0。strConn爲使用office的連接,這裏的版本號Provider=Microsoft.ACE.OLEDB.12.0對應的最高版本我這裏測試爲office2007以下均可用,以上版本未測試。

接下來就是將讀取到的datatable導入數據庫,也就是我們上面引用的dll所使用的地方。代碼如下

        /// <summary>
        /// 將datatable數據導入數據庫(使用此方法時,excel列的格式最好改爲文本,否則可能會出現爲0的現象)
        /// </summary>
        /// <param name="dt">要導入的數據</param>
        /// <param name="targetTable">導入數據庫的表名</param>
        public bool BulkToDB(DataTable dt, string targetTable)
        {
            bool res = false;
            string dbName = CommonBase.DBCommon;
            string connectionString = "鏈接數據庫的字符串";
            Oracle.DataAccess.Client.OracleConnection conn = null;
            Oracle.DataAccess.Client.OracleBulkCopy bulkCopy = null;
            try
            {
                conn = new Oracle.DataAccess.Client.OracleConnection(connectionString);
                if (conn.State != ConnectionState.Open)
                { conn.Open(); }
                bulkCopy = new Oracle.DataAccess.Client.OracleBulkCopy(conn, Oracle.DataAccess.Client.OracleBulkCopyOptions.Default);
                bulkCopy.BatchSize = 80000;//一次導入的數據量(多次循環)
                bulkCopy.BulkCopyTimeout = 360;//超時時間 總的秒數
                //targetTable目標表名
                bulkCopy.DestinationTableName = targetTable;
                if (dt != null && dt.Rows.Count != 0)
                {
                    bulkCopy.WriteToServer(dt);
                    res = true;
                }
            }
            catch (Exception ex)
            { 
                res = false;
                throw ex;
            }
            finally
            {
                if (conn != null)
                {
                    conn.Close();
                }
                if (bulkCopy != null)
                { bulkCopy.Close(); }
            }
            return res;

        }

上面的兩個方法可以直接使用,對於Oracle.DataAccess.dll這個的使用,還有幾個坑被我踩過了,希望你們看到後可以避免一下。

Oracle.DataAccess.dll應該放在bin下才能夠引用的到

如果代碼拋出System.TypeInitializationException,Oracle.DataAccess.Client.OracleConnection”的類型初始值設定項引發異常。這個問題原因就是類的靜態成員在初始化時如果出現異常,那麼訪問類的其他靜態成員或對該類進行初始化都會拋出此異常,函數失敗或者很大的可能構造函數失敗,可能是你的數據庫連接字符串有問題,需要的格式爲

 "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.000.0.000)(PORT=0000))" +
  "(CONNECT_DATA=(SID=orcl)));User Id=sys;Password=sys;";

這種格式的連接字符串,出現System.TypeInitializationException還有一種可能就是你連接數據庫的客戶端沒有安裝oracle客戶端,但其實你不必必須安裝oracle客戶端,只需要添加這四個dll在bin下。

1、oci.dll
2、oraociicus11.dll
3、OraOps11w.dll
4、oraons.dll

另外,注意你的客戶端的Oracle.DataAccess.dll使用的位數是64位版本還是32位版本的,並且上面的四個dll版本也應該與你的數據庫版本匹配。這些應該是你使用中會報錯的可能。

如果上傳大文件的excel拋出404,檢查你的iis上傳最大文件配置,如果上傳文件大小超過你的iis最大上傳量,會拋出4044的錯誤。更改最大上傳大小的方式如下修改web.config

更改節點
    更改httpRuntime節點的maxRequestLength,默認爲40960(40M),更改爲200960(200M)
    <httpRuntime executionTimeout="180" maxRequestLength="200960" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100" />


3.增加節點
    在    system.webServer節點下面增加一個
        <security>
          <requestFiltering >
            <requestLimits maxAllowedContentLength="214748364" ></requestLimits>
          </requestFiltering>
        </security>
    的節點(maxAllowedContentLength="214748364"爲200M大小)

重新生成項目,IIS中的maxrequestlength會自動變爲配置文件中的大小,如果沒有變更,那麼就把IIS的配置編輯器中的maxrequestlength變更。

希望能夠幫助到你。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章