这种方法可能不比使用StringBuilder更快,但它是可参数化的:
public void BulkInsert(string table, MySQLBulkInsertData inserts, int batchSize = 100, IProgress<double> progress = null)
{
if (inserts.Count <= 0) throw new ArgumentException("Nothing to Insert");
string insertcmd = string.Format("INSERT INTO `{0}` ({1}) VALUES ", table,
inserts.Fields.Select(p => p.FieldName).ToCSV());
StringBuilder sb = new StringBuilder();
using (MySqlConnection conn = new MySqlConnection(ConnectionString))
using (MySqlCommand sqlExecCommand = conn.CreateCommand())
{
conn.Open();
sb.AppendLine(insertcmd);
for (int i = 0; i < inserts.Count; i++)
{
sb.AppendLine(ToParameterCSV(inserts.Fields, i));
for (int j = 0; j < inserts[i].Count(); j++)
{
sqlExecCommand.Parameters.AddWithValue(string.Format("{0}{1}",inserts.Fields[j].FieldName,i), inserts[i][j]);
}
if (i > 0 && (i%batchSize == 0 || i == inserts.Count - 1))
{
sb.Append(";");
sqlExecCommand.CommandText = sb.ToString();
sqlExecCommand.ExecuteNonQuery();
sb.Clear();
sb.AppendLine(insertcmd);
if (progress != null)
{
progress.Report((double)i/inserts.Count);
}
}
else
{
sb.Append(",");
}
}
}
}
以下是使用助手类的示例:
public struct MySQLFieldDefinition
{
public MySQLFieldDefinition(string field, MySqlDbType type) : this()
{
FieldName = field;
ParameterType = type;
}
public string FieldName { get; private set; }
public MySqlDbType ParameterType { get; private set; }
}
public class MySQLBulkInsertData : List<object[]>
{
public MySQLBulkInsertData(params MySQLFieldDefinition[] fieldnames)
{
Fields = fieldnames;
}
public MySQLFieldDefinition[] Fields { get; private set; }
}
这是一个辅助方法:
private string ToParameterCSV(IEnumerable<MySQLFieldDefinition> p, int row)
{
string csv = p.Aggregate(string.Empty,
(current, i) => string.IsNullOrEmpty(current)
? string.Format("@{0}{1}",i.FieldName, row)
: string.Format("{0},@{2}{1}", current, row, i.FieldName));
return string.Format("({0})", csv);
}
也许不是非常优雅,但它可以很好地工作。我需要进度跟踪,因此这一功能被包括在其中,如果需要,可以随意删除该部分。
这将产生类似于您所需输出的SQL命令。
编辑:转CSV:
public static string ToCSV<T>(this IEnumerable<T> intValues, string separator = ",", string encloser = "")
{
string result = String.Empty;
foreach (T value in intValues)
{
result = String.IsNullOrEmpty(result)
? string.Format("{1}{0}{1}", value, encloser)
: String.Format("{0}{1}{3}{2}{3}", result, separator, value, encloser);
}
return result;
}