以前、非同期でBulkCopyするのを書いた。それのちょっと追記版。

MSDN見てたら「WriteToServerAsync」っていうのがあった。っていうか普通に非同期用のメソッドあるんじゃん・・・。とゆーことでこっちを使って書き直す。

//using System;
//using System.Data;
//using System.Data.SqlClient;

string ConnectionString = @"****";
DataTable templateDt = new DataTable();//BulkCopy用のDataTable定義テンプレ

public void sample()
{
    /*サンプルテーブル
    create table HogeTable(
        intval int,
        str1 varchar(100),
        str2 varchar(100),
        str3 varchar(100),
        str4 varchar(100),
    )
    */

    //最初にDataTableの定義を作るのメンドーなので対象テーブルを空SELECTしてSqlDataReaderから定義を作る
    using (SqlConnection cn_ = new SqlConnection(ConnectionString))
    {
        cn_.Open();
        SqlCommand command = new SqlCommand();
        command.CommandText = "select top 0 * from [HogeTable]";
        command.Connection = cn_;
        using (SqlDataReader sqlDr = command.ExecuteReader())
        {
            DataTable schemaDt = sqlDr.GetSchemaTable();
            foreach (DataRow schemaDr in schemaDt.Rows)
            {
                string columnName = schemaDr["ColumnName"].ToString().Trim();
                string dataType = schemaDr["DataType"].ToString().Trim();
                DataColumn dc = new DataColumn();
                dc.ColumnName = columnName;
                dc.DataType = System.Type.GetType(dataType);
                templateDt.Columns.Add(dc);
            }
        }
    }
    Console.WriteLine("同期実行=====");
    Console.WriteLine("Start:{0}", DateTime.Now);
    for (int i = 0; i < 3; i++)//3回やる
    {
        DataTable copyFromDataTable = CreateTestData(500000);//50万件のテストデータ
        using (SqlConnection cn_ = new SqlConnection(ConnectionString))
        {
            cn_.Open();
            using (SqlBulkCopy bulkCopy = new SqlBulkCopy(cn_))
            {
                bulkCopy.DestinationTableName = String.Format("dbo.[{0}]", "HogeTable");
                try
                {
                    bulkCopy.WriteToServer(copyFromDataTable);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }
        Console.Write("*");//進捗的な
    }
    Console.WriteLine("");
    Console.WriteLine("End:{0}", DateTime.Now);

    Console.WriteLine("非同期実行=====");
    st = DateTime.Now;
    Console.WriteLine("Start:{0}", DateTime.Now);
    for (int i = 0; i < 3; i++)//3回やる
    {
        DataTable copyFromDataTable = CreateTestData(500000);//50万件のテストデータ
        AsyncSqlBulkCopy(copyFromDataTable, String.Format("dbo.[{0}]", "HogeTable"));
        Console.Write("*");//進捗的な
    }
    Console.WriteLine("");
    ed = DateTime.Now;
    Console.WriteLine("End:{0}", DateTime.Now);

}
//非同期実行用
public async void AsyncSqlBulkCopy(DataTable bulkFrom,string distTableName)
{
    using (SqlConnection conn = new SqlConnection(ConnectionString))
    {
        await conn.OpenAsync();
        using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
        {
            bcp.DestinationTableName = distTableName;
            await bcp.WriteToServerAsync(bulkFrom);
        }
    }
}
//テストデータ作る
public DataTable CreateTestData(int count)
{
    DataTable copyFromDataTable = templateDt.Clone();
    string kyedatetime = DateTime.Now.ToString("yyyyMMddHHmmssfff");
    for (int i = 0; i < count; i++)
    {
        var addRow = copyFromDataTable.NewRow();
        addRow.BeginEdit();
        addRow[0] = i;
        addRow[1] = String.Format("str1_{0}", kyedatetime);
        addRow[2] = String.Format("str2_{0}", kyedatetime);
        addRow[3] = String.Format("str3_{0}", kyedatetime);
        addRow[4] = String.Format("str4_{0}", kyedatetime);
        addRow.EndEdit();
        copyFromDataTable.Rows.Add(addRow);
    }
    return copyFromDataTable;
}

非同期の方が同期実行時の半分くらいの時間だった。まぁデータが登録終わるまでの時間は変わんないけどネ。。。

ちなみにDestinationTableName にはちゃんと"[テーブル名]"の形でテーブル名を指定したほうが吉。[]で囲ってないとやられる場合がある故。