原創文章, 寫文章不易,轉載請標明!
最近工作需要用到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變更。
希望能夠幫助到你。