C# 使用MySqlBulkLoader 批量导入数据到Mysql

怼烎@ 2022-08-21 03:16 941阅读 0赞

前言:

最近做了一个导入数据的功能,需求大概是这样的,有张Excel表格,将里面的数据插入到mysql已经建好的表里面,而且字段要一一对应,之前我们用的是SqlServer数据库,实现这个批量插入的工作就很简单了,我们可以用SqlBulkCopy批量更新数据,但是在Mysql的ADO操作对象中并没有这个对象,难道要去拼接Insert语句么?小编找到了这样一个有用的对象—— MySqlBulkLoader,是先将DATATable编程CSV文件, 在用MySqlBulkLoader导入MySql中,这样的操作很简单,下面是我的实现。

SouthEast

代码实现:

逻辑层:

  1. <span style="font-family:KaiTi_GB2312;font-size:18px;"> #region ImportQuestionFile() 导入Excel模板题--周洲--2016年3月11日20:42:53
  2. /// <summary>
  3. /// 导入Excel模板题--周洲--2016年3月11日20:42:53
  4. /// </summary>
  5. /// <param name="filePathName"></param>
  6. /// <param name="strPaperId"></param>
  7. /// <returns></returns>
  8. public Dictionary<int, DataTable> ImportQuestionFile(string filePathName, string strPaperId)
  9. {
  10. //完整文件路径
  11. string strFilePath = _savePath1 + filePathName;
  12. //添加默认列(时间戳,是否删除等)
  13. Dictionary<string, string> defaultField = new Dictionary<string, string>();
  14. //defaultField.Add("CourseID", strPaperId);
  15. defaultField.Add("TimeSpan", DateTime.Now.ToString());
  16. //调用底层的方法
  17. Dictionary<int, DataTable> ta = new Dictionary<int, DataTable>();
  18. ExcelImportManager excelImportManager = new ExcelImportManager();
  19. ta = excelImportManager.ImportExcel(strFilePath, "Panduanti", defaultField, "itooexamEntities");
  20. return ta;
  21. }
  22. #endregion
  23. </span>

调用的ExcelImportManager里面的ImportExcel方法:

  1. <span style="font-family:KaiTi_GB2312;font-size:18px;"> public Dictionary<int, DataTable> ImportExcel(string strPath, string strXMLName, Dictionary<string, string> dicDefaultColumn, string strDBKey)
  2. {
  3. //得到导入目标表的DataTable
  4. Dictionary<int, DataTable> dicTargetTable = this.GetImportTable(strPath, strXMLName, dicDefaultColumn, strDBKey);
  5. //得到导入第三张表的DataTable
  6. Dictionary<int, DataTable> dicThirdTable = this.GetThirdTable();
  7. //得到过程中出现的问题表
  8. Dictionary<int, DataTable> dicErrorTable = this.GetErrorTable();
  9. //执行隐式事务
  10. // try
  11. // {
  12. using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
  13. {
  14. for (int intTableIndex = 0; intTableIndex < dicTargetTable.Count; intTableIndex++)
  15. {
  16. if (dicTargetTable[intTableIndex].Rows.Count > 0)
  17. {
  18. DataTable dtTarget = dicTargetTable[intTableIndex];
  19. //TODO:从这里调用导入数据库的方法,在sqlhelper中
  20. // sqlHelper.InsertTable(strPath, strDBKey, dtTarget, dtTarget.TableName, dtTarget.Columns);
  21. //MySqlDBHelper mysqlhelper = new MySqlDBHelper();
  22. //mysqlhelper.BulkInsert(strDBKey,dtTarget);
  23. string strConnValue = ConfigHelper.ReadAppSetting(strDBKey);
  24. MySqlHelper mysqlhelper = new MySqlHelper(strConnValue);
  25. mysqlhelper.BulkInsert(dtTarget);
  26. }
  27. }
  28. scope.Complete();
  29. }
  30. // }
  31. //catch (Exception e)
  32. // {
  33. // throw new Exception(e.Message);
  34. // }
  35. Boolean bolIsExistErrorData = false;
  36. foreach (int intErrorTableIndex in dicErrorTable.Keys)
  37. {
  38. if (dicErrorTable[intErrorTableIndex].Rows.Count > 0)
  39. {
  40. bolIsExistErrorData = true;
  41. }
  42. }
  43. if (bolIsExistErrorData)
  44. {
  45. return dicErrorTable;
  46. }
  47. return null;
  48. }</span>

调用的数据库操作类:mysqlhelper

  1. <span style="font-family:KaiTi_GB2312;font-size:18px;"> /// <summary>
  2. ///大批量数据插入,返回成功插入行数
  3. /// </summary>
  4. /// <param name="connectionString">数据库连接字符串</param>
  5. /// <param name="table">数据表</param>
  6. /// <returns>返回成功插入行数</returns>
  7. public static int BulkInsert(string connectionString, DataTable table)
  8. {
  9. if (string.IsNullOrEmpty(table.TableName)) throw new Exception("请给DataTable的TableName属性附上表名称");
  10. if (table.Rows.Count == 0) return 0;
  11. int insertCount = 0;
  12. string tmpPath = Path.GetTempFileName();
  13. string csv = DataTableToCsv(table);
  14. File.WriteAllText(tmpPath, csv);
  15. // MySqlTransaction tran = null;
  16. using (MySqlConnection conn = new MySqlConnection(connectionString))
  17. {
  18. try
  19. {
  20. conn.Open();
  21. //tran = conn.BeginTransaction();
  22. MySqlBulkLoader bulk = new MySqlBulkLoader(conn)
  23. {
  24. FieldTerminator = ",",
  25. FieldQuotationCharacter = '"',
  26. EscapeCharacter = '"',
  27. LineTerminator = "\r\n",
  28. FileName = tmpPath,
  29. NumberOfLinesToSkip = 0,
  30. TableName = table.TableName,
  31. };
  32. //bulk.Columns.AddRange(table.Columns.Cast<DataColumn>().Select(colum => colum.ColumnName).ToArray());
  33. insertCount = bulk.Load();
  34. // tran.Commit();
  35. }
  36. catch (MySqlException ex)
  37. {
  38. // if (tran != null) tran.Rollback();
  39. throw ex;
  40. }
  41. }
  42. File.Delete(tmpPath);
  43. return insertCount;
  44. }</span>
  45. <span style="font-family:KaiTi_GB2312;font-size:18px;"> /// <summary>
  46. ///将DataTable转换为标准的CSV
  47. /// </summary>
  48. /// <param name="table">数据表</param>
  49. /// <returns>返回标准的CSV</returns>
  50. private static string DataTableToCsv(DataTable table)
  51. {
  52. //以半角逗号(即,)作分隔符,列为空也要表达其存在。
  53. //列内容如存在半角逗号(即,)则用半角引号(即"")将该字段值包含起来。
  54. //列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。
  55. StringBuilder sb = new StringBuilder();
  56. DataColumn colum;
  57. foreach (DataRow row in table.Rows)
  58. {
  59. for (int i = 0; i < table.Columns.Count; i++)
  60. {
  61. colum = table.Columns[i];
  62. if (i != 0) sb.Append(",");
  63. if (colum.DataType == typeof(string) && row[colum].ToString().Contains(","))
  64. {
  65. sb.Append("\"" + row[colum].ToString().Replace("\"", "\"\"") + "\"");
  66. }
  67. else sb.Append(row[colum].ToString());
  68. }
  69. sb.AppendLine();
  70. }
  71. return sb.ToString();
  72. }
  73. </span>
  74. <span style="font-family:KaiTi_GB2312;font-size:18px;"> /// <summary>
  75. ///大批量数据插入,返回成功插入行数
  76. /// </summary>
  77. /// <param name="table">数据表</param>
  78. /// <returns>返回成功插入行数</returns>
  79. public int BulkInsert(DataTable table)
  80. {
  81. return BulkInsert(ConnectionString, table);
  82. }
  83. </span>

Panduanti.xml文件,用来获取表信息和数据类型的验证

  1. <span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="utf-8" ?>
  2. <Excel name="判断题导入模板">
  3. <Sheet name="判断题" table="t_sixiu_panduanti" primaryKey="QuestionID" pkType="int">
  4. <Column name="题号" field="QuestionID" isNecessary="true" >
  5. <DataType>int</DataType>
  6. <ForeignKey isExist="false"></ForeignKey>
  7. </Column>
  8. <Column name="章节" field="ChapterID" >
  9. <DataType>string</DataType>
  10. <ForeignKey isExist="false"></ForeignKey>
  11. </Column>
  12. <Column name="题型" field="QuestionTypeID" >
  13. <DataType>string</DataType>
  14. <ForeignKey isExist="false"></ForeignKey>
  15. </Column>
  16. <Column name="难度等级" field="Degree">
  17. <DataType>string</DataType>
  18. <ForeignKey isExist="false"></ForeignKey>
  19. </Column>
  20. <Column name="总分值" field="Fraction">
  21. <DataType>float</DataType>
  22. <ForeignKey isExist="false"></ForeignKey>
  23. </Column>
  24. <Column name="主题干" field="QuestionContent">
  25. <DataType>string</DataType>
  26. <ForeignKey isExist="false"></ForeignKey>
  27. </Column>
  28. <Column name="标准答案" field="CorrectAnswer">
  29. <DataType>string</DataType>
  30. <ForeignKey isExist="false"></ForeignKey>
  31. </Column>
  32. <Column name="有效性(T or F)" field="IsValid" >
  33. <DataType>string</DataType>
  34. <ForeignKey isExist="false"></ForeignKey>
  35. </Column>
  36. <Column name="是否为听力(T or F)" field="other2">
  37. <DataType>string</DataType>
  38. <ForeignKey isExist="false"></ForeignKey>
  39. </Column>
  40. </Sheet>
  41. </Excel>
  42. </span>
  43. 这样就简单的实现了一个批量上传的功能,跟拼接insert语句比起来,我还是选择这样的方法,方便省事的批量插入。

总结:

1.一个功能实现,找方法的过程可能比你实现花费的时间长的很多,那也一定要耐得住性子去查,有很多不知道的东西,在等着你。

2.在发现mysql没有这个SqlBulkCopy的时候,我就知道一定有一个它的替代品,哈哈,果然找到了。

发表评论

表情:
评论列表 (有 0 条评论,941人围观)

还没有评论,来说两句吧...

相关阅读

    相关 MySqlBulkLoader 批量導入漏資料

    1.導入資料中有uid,且表中uid為自增長性的關鍵字 空uid插入后自動產生新的佔位,當下一個不為空這個值的uid插入時碰到就無法插入 2.導入表設有唯一關鍵字段,而導入