C# 使用MySqlBulkLoader 批量匯入資料到Mysql
阿新 • • 發佈:2019-01-28
前言:
最近做了一個匯入資料的功能,需求大概是這樣的,有張Excel表格,將裡面的資料插入到mysql已經建好的表裡面,而且欄位要一一對應,之前我們用的是SqlServer資料庫,實現這個批量插入的工作就很簡單了,我們可以用SqlBulkCopy批量更新資料,但是在Mysql的ADO操作物件中並沒有這個物件,難道要去拼接Insert語句麼?小編找到了這樣一個有用的物件—— MySqlBulkLoader,是先將DATATable程式設計CSV檔案, 在用MySqlBulkLoader匯入MySql中,這樣的操作很簡單,下面是我的實現。
程式碼實現:
邏輯層:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> #region ImportQuestionFile() 匯入Excel模板題--周洲--2016年3月11日20:42:53 /// <summary> /// 匯入Excel模板題--周洲--2016年3月11日20:42:53 /// </summary> /// <param name="filePathName"></param> /// <param name="strPaperId"></param> /// <returns></returns> public Dictionary<int, DataTable> ImportQuestionFile(string filePathName, string strPaperId) { //完整檔案路徑 string strFilePath = _savePath1 + filePathName; //新增預設列(時間戳,是否刪除等) Dictionary<string, string> defaultField = new Dictionary<string, string>(); //defaultField.Add("CourseID", strPaperId); defaultField.Add("TimeSpan", DateTime.Now.ToString()); //呼叫底層的方法 Dictionary<int, DataTable> ta = new Dictionary<int, DataTable>(); ExcelImportManager excelImportManager = new ExcelImportManager(); ta = excelImportManager.ImportExcel(strFilePath, "Panduanti", defaultField, "itooexamEntities"); return ta; } #endregion </span>
呼叫的ExcelImportManager裡面的ImportExcel方法:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> public Dictionary<int, DataTable> ImportExcel(string strPath, string strXMLName, Dictionary<string, string> dicDefaultColumn, string strDBKey) { //得到匯入目標表的DataTable Dictionary<int, DataTable> dicTargetTable = this.GetImportTable(strPath, strXMLName, dicDefaultColumn, strDBKey); //得到匯入第三張表的DataTable Dictionary<int, DataTable> dicThirdTable = this.GetThirdTable(); //得到過程中出現的問題表 Dictionary<int, DataTable> dicErrorTable = this.GetErrorTable(); //執行隱式事務 // try // { using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew)) { for (int intTableIndex = 0; intTableIndex < dicTargetTable.Count; intTableIndex++) { if (dicTargetTable[intTableIndex].Rows.Count > 0) { DataTable dtTarget = dicTargetTable[intTableIndex]; //TODO:從這裡呼叫匯入資料庫的方法,在sqlhelper中 // sqlHelper.InsertTable(strPath, strDBKey, dtTarget, dtTarget.TableName, dtTarget.Columns); //MySqlDBHelper mysqlhelper = new MySqlDBHelper(); //mysqlhelper.BulkInsert(strDBKey,dtTarget); string strConnValue = ConfigHelper.ReadAppSetting(strDBKey); MySqlHelper mysqlhelper = new MySqlHelper(strConnValue); mysqlhelper.BulkInsert(dtTarget); } } scope.Complete(); } // } //catch (Exception e) // { // throw new Exception(e.Message); // } Boolean bolIsExistErrorData = false; foreach (int intErrorTableIndex in dicErrorTable.Keys) { if (dicErrorTable[intErrorTableIndex].Rows.Count > 0) { bolIsExistErrorData = true; } } if (bolIsExistErrorData) { return dicErrorTable; } return null; }</span>
呼叫的資料庫操作類:mysqlhelper
<span style="font-family:KaiTi_GB2312;font-size:18px;"> /// <summary> ///大批量資料插入,返回成功插入行數 /// </summary> /// <param name="connectionString">資料庫連線字串</param> /// <param name="table">資料表</param> /// <returns>返回成功插入行數</returns> public static int BulkInsert(string connectionString, DataTable table) { if (string.IsNullOrEmpty(table.TableName)) throw new Exception("請給DataTable的TableName屬性附上表名稱"); if (table.Rows.Count == 0) return 0; int insertCount = 0; string tmpPath = Path.GetTempFileName(); string csv = DataTableToCsv(table); File.WriteAllText(tmpPath, csv); // MySqlTransaction tran = null; using (MySqlConnection conn = new MySqlConnection(connectionString)) { try { conn.Open(); //tran = conn.BeginTransaction(); MySqlBulkLoader bulk = new MySqlBulkLoader(conn) { FieldTerminator = ",", FieldQuotationCharacter = '"', EscapeCharacter = '"', LineTerminator = "\r\n", FileName = tmpPath, NumberOfLinesToSkip = 0, TableName = table.TableName, }; //bulk.Columns.AddRange(table.Columns.Cast<DataColumn>().Select(colum => colum.ColumnName).ToArray()); insertCount = bulk.Load(); // tran.Commit(); } catch (MySqlException ex) { // if (tran != null) tran.Rollback(); throw ex; } } File.Delete(tmpPath); return insertCount; }</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;"> /// <summary>
///將DataTable轉換為標準的CSV
/// </summary>
/// <param name="table">資料表</param>
/// <returns>返回標準的CSV</returns>
private static string DataTableToCsv(DataTable table)
{
//以半形逗號(即,)作分隔符,列為空也要表達其存在。
//列內容如存在半形逗號(即,)則用半形引號(即"")將該欄位值包含起來。
//列內容如存在半形引號(即")則應替換成半形雙引號("")轉義,並用半形引號(即"")將該欄位值包含起來。
StringBuilder sb = new StringBuilder();
DataColumn colum;
foreach (DataRow row in table.Rows)
{
for (int i = 0; i < table.Columns.Count; i++)
{
colum = table.Columns[i];
if (i != 0) sb.Append(",");
if (colum.DataType == typeof(string) && row[colum].ToString().Contains(","))
{
sb.Append("\"" + row[colum].ToString().Replace("\"", "\"\"") + "\"");
}
else sb.Append(row[colum].ToString());
}
sb.AppendLine();
}
return sb.ToString();
}
</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;"> /// <summary>
///大批量資料插入,返回成功插入行數
/// </summary>
/// <param name="table">資料表</param>
/// <returns>返回成功插入行數</returns>
public int BulkInsert(DataTable table)
{
return BulkInsert(ConnectionString, table);
}
</span>
Panduanti.xml檔案,用來獲取表資訊和資料型別的驗證
<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="utf-8" ?>
<Excel name="判斷題匯入模板">
<Sheet name="判斷題" table="t_sixiu_panduanti" primaryKey="QuestionID" pkType="int">
<Column name="題號" field="QuestionID" isNecessary="true" >
<DataType>int</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
<Column name="章節" field="ChapterID" >
<DataType>string</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
<Column name="題型" field="QuestionTypeID" >
<DataType>string</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
<Column name="難度等級" field="Degree">
<DataType>string</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
<Column name="總分值" field="Fraction">
<DataType>float</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
<Column name="主題幹" field="QuestionContent">
<DataType>string</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
<Column name="標準答案" field="CorrectAnswer">
<DataType>string</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
<Column name="有效性(T or F)" field="IsValid" >
<DataType>string</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
<Column name="是否為聽力(T or F)" field="other2">
<DataType>string</DataType>
<ForeignKey isExist="false"></ForeignKey>
</Column>
</Sheet>
</Excel>
</span>
這樣就簡單的實現了一個批量上傳的功能,跟拼接insert語句比起來,我還是選擇這樣的方法,方便省事的批量插入。
總結:
1.一個功能實現,找方法的過程可能比你實現花費的時間長的很多,那也一定要耐得住性子去查,有很多不知道的東西,在等著你。
2.在發現mysql沒有這個SqlBulkCopy的時候,我就知道一定有一個它的替代品,哈哈,果然找到了。