将DataTable批量复制到MySQL(类似于System.Data.SqlClient.SqlBulkCopy)

Mic*_*egg 15 c# mysql database

我正在将我的程序从Microsoft SQL Server迁移到MySQL.一切正常,除了批量复制的一个问题.

在使用MS SQL的解决方案中,代码如下所示:

connection.Open();
SqlBulkCopy bulkCopy = new SqlBulkCopy(connection);
bulkCopy.DestinationTableName = "testTable";
bulkCopy.WriteToServer(rawData);
Run Code Online (Sandbox Code Playgroud)

现在我尝试为MySQL做类似的事情.因为我认为会有不好的性能,所以我不想将DataTable写入CSV文件并从那里开始插入MySqlBulkLoader类.

任何帮助将受到高度赞赏.

Gor*_*son 15

因为我认为会有糟糕的性能,所以我不想将DataTable写入CSV文件,并使用MySqlBulkLoader类从那里进行插入.

不排除基于毫无根据的假设的可能解决方案.我只是测试的从100,000行插入System.Data.DataTable使用标准到MySQL表MySqlDataAdapter#Update()Transaction.它一直需要大约30秒才能运行:

using (MySqlTransaction tran = conn.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
    using (MySqlCommand cmd = new MySqlCommand())
    {
        cmd.Connection = conn;
        cmd.Transaction = tran;
        cmd.CommandText = "SELECT * FROM testtable";
        using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
        {
            da.UpdateBatchSize = 1000;
            using (MySqlCommandBuilder cb = new MySqlCommandBuilder(da))
            {
                da.Update(rawData);
                tran.Commit();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(我尝试了几个不同的值,UpdateBatchSize但它们似乎没有对经过的时间产生重大影响.)

相比之下,以下代码使用MySqlBulkLoader只需5或6秒即可运行...

string tempCsvFileSpec = @"C:\Users\Gord\Desktop\dump.csv";
using (StreamWriter writer = new StreamWriter(tempCsvFileSpec))
{
    Rfc4180Writer.WriteDataTable(rawData, writer, false);
}
var msbl = new MySqlBulkLoader(conn);
msbl.TableName = "testtable";
msbl.FileName = tempCsvFileSpec;
msbl.FieldTerminator = ",";
msbl.FieldQuotationCharacter = '"';
msbl.Load();
System.IO.File.Delete(tempCsvFileSpec);
Run Code Online (Sandbox Code Playgroud)

...包括将DataTable中的100,000行转储到临时CSV文件(使用与此类似的代码),从该文件批量加载以及之后删除文件的时间.


sus*_*har 6

与SqlBulkCopy类似,我们为Mysql提供了MySqlBulkCopy。这是如何使用它的示例。

public async Task<bool> MySqlBulCopyAsync(DataTable dataTable)
    {
        try
        {
            bool result = true;
            using (var connection = new MySqlConnector.MySqlConnection(_connString + ";AllowLoadLocalInfile=True"))
            {
                await connection.OpenAsync();
                var bulkCopy = new MySqlBulkCopy(connection);
                bulkCopy.DestinationTableName = "yourtable";
                // the column mapping is required if you have a identity column in the table
                bulkCopy.ColumnMappings.AddRange(GetMySqlColumnMapping(dataTable));
                await bulkCopy.WriteToServerAsync(dataTable);
                return result;
            }
        }
        catch (Exception ex)
        {
            throw;
        }
    }
    private List<MySqlBulkCopyColumnMapping> GetMySqlColumnMapping(DataTable dataTable)
    {
        List<MySqlBulkCopyColumnMapping> colMappings = new List<MySqlBulkCopyColumnMapping>();
        int i = 0;
        foreach (DataColumn col in dataTable.Columns)
        {
            colMappings.Add(new MySqlBulkCopyColumnMapping(i, col.ColumnName));
            i++;
        }
        return colMappings;
    }
Run Code Online (Sandbox Code Playgroud)

如果表中没有任何标识列,则可以忽略列映射。如果你有标识列,那么你必须使用列映射,否则它不会在表中插入任何记录,它只会给出类似“x 行已复制,但仅插入 0 行”的消息。

这个类可在下面的库 Assembly MySqlConnector 中找到,版本=1.0.0.0


ale*_*lex 5

使用任何 BulkOperation NuGet 包,您都可以轻松完成此操作。

这是使用https://www.nuget.org/packages/Z.BulkOperations/2.14.3/中的包的示例

MySqlConnection conn = DbConnection.OpenConnection();
DataTable dt = new DataTable("testtable");
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM testtable", conn);
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
da.Fill(dt);
Run Code Online (Sandbox Code Playgroud)

而不是使用

......
da.UpdateBatchSize = 1000;
......
da.Update(dt)
Run Code Online (Sandbox Code Playgroud)

只需遵循两行

var bulk = new BulkOperation(conn);
bulk.BulkInsert(dt);
Run Code Online (Sandbox Code Playgroud)

只需 5 秒即可将整个 DataTable 复制到 MySQL,而无需先将 DataTable 中的 100,000 行转储到临时 CSV 文件中。