最近做了一个导入数据的功能,需求大概是这样的,有张Excel表格,将里面的数据插入到mysql已经建好的表里面,而且字段要一一对应,之前我们用的是SqlServer数据库,实现这个批量插入的工作就很简单了,我们可以用SqlBulkCopy批量更新数据,但是在Mysql的ADO操作对象中并没有这个对象,难道要去拼接Insert语句么?小编找到了这样一个有用的对象—— MySqlBulkLoader,是先将DATATable编程CSV文件, 在用MySqlBulkLoader导入MySql中,这样的操作很简单,下面是我的实现。
逻辑层:
#region ImportQuestionFile() 导入Excel模板题--周洲--2016年3月11日20:42:53
///
/// 导入Excel模板题--周洲--2016年3月11日20:42:53
///
///
///
///
public Dictionary ImportQuestionFile(string filePathName, string strPaperId)
{
//完整文件路径
string strFilePath = _savePath1 + filePathName;
//添加默认列(时间戳,是否删除等)
Dictionary defaultField = new Dictionary();
//defaultField.Add("CourseID", strPaperId);
defaultField.Add("TimeSpan", DateTime.Now.ToString());
//调用底层的方法
Dictionary ta = new Dictionary();
ExcelImportManager excelImportManager = new ExcelImportManager();
ta = excelImportManager.ImportExcel(strFilePath, "Panduanti", defaultField, "itooexamEntities");
return ta;
}
#endregion
调用的ExcelImportManager里面的ImportExcel方法:
public Dictionary ImportExcel(string strPath, string strXMLName, Dictionary dicDefaultColumn, string strDBKey)
{
//得到导入目标表的DataTable
Dictionary dicTargetTable = this.GetImportTable(strPath, strXMLName, dicDefaultColumn, strDBKey);
//得到导入第三张表的DataTable
Dictionary dicThirdTable = this.GetThirdTable();
//得到过程中出现的问题表
Dictionary 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;
}
///
///大批量数据插入,返回成功插入行数
///
/// 数据库连接字符串
/// 数据表
/// 返回成功插入行数
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().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;
}
///
///将DataTable转换为标准的CSV
///
/// 数据表
/// 返回标准的CSV
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();
}
///
///大批量数据插入,返回成功插入行数
///
/// 数据表
/// 返回成功插入行数
public int BulkInsert(DataTable table)
{
return BulkInsert(ConnectionString, table);
}
Panduanti.xml文件,用来获取表信息和数据类型的验证
int
string
string
string
float
string
string
string
string
1.一个功能实现,找方法的过程可能比你实现花费的时间长的很多,那也一定要耐得住性子去查,有很多不知道的东西,在等着你。
2.在发现mysql没有这个SqlBulkCopy的时候,我就知道一定有一个它的替代品,哈哈,果然找到了。