私の現在のプロジェクトは、データ、ビジネス、プレゼンテーションの3つの標準レイヤーで構成されています。すべてのデータアクセスのニーズにデータエンティティを使用したいと思います。アプリの機能の一部として、フラットファイル内のすべてのデータをデータベースにコピーする必要があります。ファイルはそれほど大きくないので、SqlBulkCopyを使用できます。 .NETでのSqlBulkCopyクラスの使用法に関する記事をいくつか見つけました。ただし、すべての記事でDataTablesを使用してデータを前後に移動しています。
SqlBulkCopyと一緒にデータエンティティを使用する方法はありますか、それともDataTablesを使用する必要がありますか?
エンティティをIDataReaderまたはDataTableに変換する必要があります。
以下を支援するように設計された小さなヘルパークラスがあります: http://archive.msdn.Microsoft.com/LinqEntityDataReader/Release/ProjectReleases.aspx?ReleaseId=389
編集:msdnリンクが壊れています、代替コピーはここにあります: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs
次に、次のようにSqlBulkCopyを使用できます。
var sbCopy= new SqlBulkCopy(connectionString);
sbCopy.DestinationTableName = "TableName";
sbCopy.WriteToServer(entitiesList.AsDataReader());
EFを使用して一括挿入するときに、いくつかのアプローチを試し、テストしました。最終的には、さまざまな行サイズで最高のパフォーマンスを実現するために、テーブル値のパラメーターを使用しました。手元にある数値はありませんが、これはわかっています bcp/BULK INSERTのパフォーマンスとテーブル値パラメーターのパフォーマンス が指針となりました。
もともとはSqlBulkCopy
を使用し、IEnumerable<T>
を取得してIDataReader
を作成するアダプターを組み合わせました。また、SqlBulkCopyに関連するメタデータも生成しました。ここでの利点は、インポートがコードのみであるということでした。 @davehoganが投稿したコードは、このための基礎として使用されました。
テーブル値パラメーターには、データベースで定義されたストアード・プロシージャーとテーブル・タイプが必要です。コードファーストを使用している場合は、SQLを実行して、作成スクリプトの一部としてこれらを作成できます。これはより多くの作業ですが、データベースへの行のスループットが大幅に向上し、より高速になることがわかりました。
また、メインテーブルにnot一括挿入することを検討する価値があります。一時ヒープテーブルを使用し、データがインポートされたら、それにクラスター化インデックスを追加します。次に、一時テーブルとメインテーブルの間でMERGE
を実行します。これには、挿入中にメインテーブルのインデックスをロックしないという利点があり、同時実行性が向上します。この方法を使用すると、CPUごとに2500行/秒以上が挿入される傾向があります。
さらに情報が必要な場合はお知らせください。
バルクパッケージ ライブラリを使用できます。 Bulk Insert 1.0.0バージョンは、Entity Framework> = 6.0.0のプロジェクトで使用されます。詳細については、以下のリンクを参照してください- バルク操作のソースコード
EFCoreの場合、BulkExtensions(Insert、InsertOrUpdate Update、Delete)は次のとおりです。
リンク: https://github.com/borisdj/EFCore.BulkExtensions
Nuget からインストールすることもできます
SqlBulkCopyは、クライアントからSQLServerへの行データの直接のほぼバイト配列のような転送です。これは、SQLServerにデータを取り込むための最も効率的な方法です。
ただし、そのパフォーマンスは、真に「バルク」操作にあります。数百または数千の行は、使用を正当化するのに必ずしも十分な高さではありません。数万から数百万の行がSqlBulkCopyのパフォーマンスを本当に輝かせます。そして、結局、私たちが本当に話しているのは、データを取得することだけですサーバーに。
行のセットを本番データベースのテーブルに入れるには、他にも重要な課題があります。インデックスの再作成、並べ替え(クラスター化インデックスがある場合)、外部キーの検証、これらすべての種類の処理により、挿入に時間がかかり、テーブルとインデックスがロックされる可能性があります。
また、TVPデータは(一時テーブルデータとして)ディスクに書き込まれ、テーブルに配置するためにアクセスできます。 SqlBulkCopyは、テーブルに直接アクセスできます...その場合のパフォーマンスは大幅に高速になりますが、同時実行の速度のバランスをとる必要があります。
全体的なルールは、処理する行が少数の場合はTVPを考え、数千の行がある場合は、SqlBulkCopyを介してできるだけ早くSQLServerに到達することを検討することだと思います。
SqlBulkCopyは、WriteToServerメソッドを呼び出すときにIDataReaderを使用するため、IEnumerableであるコレクションに基づいてIDataReaderを実装できるはずです。これにより、エンティティセットを取り込み、IDataReader実装を使用してSqlBulkCopyを呼び出すことができます。
データセットは、データエンティティのシリアル化と見なすことができます。ただし、一般的に言えば、SqlBulkCopyはテーブル間のものであると思います。したがって、datatablesの理由です。