2012-03-08 14 views
1

私たちのアプリでは大きなパフォーマンス上の問題があり、異なるシステムからデータを収集し、DBに保存して後でレポートを生成します。Bulk inserts with EF4.2

エンティティフレームワーク4.2とDbSetsを使用していますが、DbSetの各エンティティのAddメソッドをバルク挿入する方法がありますか?追加ロジック

oneThousandCustomers.Foreach(c => context.Customers.Add(c)); //This will take a minute 
context.SaveChanges(); //This takes under a second 

を持つ巨大なパフォーマンスの問題があるので、私は、addメソッドは、ボンネットの下にたくさんのルックアップなどとものをやっていると思いますが、私はちょうどバルクにこのデータを挿入します。出来ますか?

答えて

1

ここでは、コレクションにアイテムを追加するときに、EFがシーンの中でたくさんのものを処理するということです。

パフォーマンス面で本当に大きな点は、オブジェクトグラフ全体を列挙するaddコマンドごとにDetectChanges()を自動的に呼び出すことです。

これは、現在のEFコンテキストによって大量のアイテムが追跡されている場合、これは実際に重大なパフォーマンス上の問題を引き起こすことを意味します。

パフォーマンスを向上させるためのヒントをいくつか紹介します。比較として、FKのないかなり単純なエンティティを1/2秒未満で挿入できます。

  • あなたのクエリのための新しいEFコンテキスト・インスタンスを使用していることを確認し、 これはあなたの変化グラフはそうかなり速い になります追加小規模であることを確認します。
  • それはEFのそのほとんどを意味するあなたは少し注意する必要がありAutoDetectChangesを無効にすると自動検出の変更

    context.Configuration.AutoDetectChangesEnabled = false; 
    

    をオフにするDbContext

コードの自動変化検出の電源を入れオートマティックがオフになっているので、特にナビゲーションプロパティを使用している場合や、既存のエンティティを更新している場合に、奇妙なことが起こる可能性があります。これらの問題を解決するには、SaveChangesを呼び出す直前にDetectChangesを呼び出します。これはパフォーマンスを低下させ、単純な追加操作では必要ないので、あなたの例ではこれがなくても逃げ出すことができます。これについて

このMSDNの記事交渉、(4でさえそのEF 5その同じかかわらを注意してください)http://msdn.microsoft.com/en-us/library/gg696177%28v=vs.103%29.aspx

+0

CQRSフレームワークを使用し、コンテキストごとにコンテキストが注入されるため、コンテキストの動作を変更することは少し危険です。コンテキストの動作を変更した後、コマンドロジックの他の部分がコンテキストを使用しないという保証はないからです。 – Anders

+0

パフォーマンスが危険であり、妥協が必要な場合は、EFの利点が必要な場合は、パフォーマンスの問題を解決するか、手動でコンテキストを管理してパフォーマンスを最適化する必要があります。これをやりたくない場合は、EFを使用しないでください。しかし、私はCQRS、メッセージングと一括インポート、EF(クエリーとライトの両方)と全く同じことを行い、うまく動作します。 –

+0

既存のコードを変更するのはとても簡単だったので、これを選択します。すべてのユニットテストとシナリオテストは緑色なので、動作しているようです!ありがとう! – Anders

0

LinqEntityDataReaderを使用すると、エンティティコレクションでSqlBulkCopyを実行できます。これにより、アプリケーションのパフォーマンス入力リンクの説明が改善されます。

+0

は、おかげでそれをチェックアウトします! – Anders