単純なオブジェクトのList <>からSqlBulkCopyで大きな挿入を行うにはどうすればよいですか?
カスタムIDataReaderを実装しますか?
オブジェクトのリストから単純に DataTableを作成 し、SqlBulkCopy.WriteToServer
を呼び出して、データテーブルを渡します。
次のものが役立つ場合があります。
SqlBulkCopyで最大のパフォーマンスを得るには、適切な BatchSize を設定する必要があります。 10,000はうまく機能するようですが、データのプロファイルを作成してください。
SqlBulkCopyOptions.TableLock を使用すると、より良い結果が得られる場合もあります。
SqlBulkCopyパフォーマンスの興味深く有益な分析が見つかります here 。
FastMember を使用すると、DataTable
(私のテストではパフォーマンスが2倍以上)を経由することなくこれを実行できます。
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description"))
{
bcp.DestinationTableName = "SomeTable";
bcp.WriteToServer(reader);
}
ObjectReader
は一般的でないソースでも機能することに注意してください。また、事前にメンバー名を指定する必要はありません(ただし、ColumnMappings
アスペクトのSqlBulkCopy
ObjectReader
自体で指定しない場合)。
パーティーには遅刻しますが、MicrosoftからこのEntityDataReader
クラスを追加する場合、これを行うAsDataReader()
拡張メソッドがあります。 https://github.com/matthewschrager/リポジトリ/blob/master/Repository.EntityFramework/EntityDataReader.cs
(例[List].AsDataReader()
実装:)
var connStr = "";
using (var connection = new SqlConnection(connStr))
{
var startTime = DateTime.Now;
connection.Open();
var transaction = connection.BeginTransaction();
try
{
//var connStr = connection.ConnectionString;
using (var sbCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
{
sbCopy.BulkCopyTimeout = 0;
sbCopy.BatchSize = 10000;
sbCopy.DestinationTableName = "Foobars";
var reader = Foobars.AsDataReader();
sbCopy.WriteToServer(reader);
}
transaction.Commit();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
transaction.Rollback();
}
finally
{
transaction.Dispose();
connection.Close();
var endTime = DateTime.Now;
Console.WriteLine("Upload time elapsed: {0} seconds", (endTime - startTime).TotalSeconds);
}
}
最初にSqlBulkCopy
を呼び出して何を達成しようとしているのかによっては、テーブル値パラメーター(TVP)を使用する方が理にかなっている場合があります。 TVPを使用すると、カスタムタイプのコレクションを送信するのが簡単になります。データをストリームインできるため、DataTable
を回避でき(@Marc Gravellの回答と同様)、SqlBulkCopy
も回避できます。 TVPは、ストアドプロシージャを呼び出してTVPデータを渡し、INSERT
(これは、 SqlBulkCopy
の場合)。また、新しく作成されたSqlDataReader
値などのIDENTITY
データを介してデータを取得することもできます。この回答に例といくつかの追加メモを追加しました: 可能な限り最短時間で1000万レコードを挿入するにはどうすればよいですか? 。そして数年前、私はSQL Server Central(無料の登録が必要です) アプリケーションからSQL Server 2008へのデータのストリーミング に関する記事を書きました。これは、リンクされた回答にも記載されており、 300万行のテキストファイルからストリーミングされたカスタムタイプのジェネリックリスト。