web-dev-qa-db-ja.com

DbContextは、追加および削除時に非常に遅い

データベース優先シナリオでDbContextを使用すると、エンティティの追加と削除がObjectContextと比較して非常に遅いことがわかりました。 2000個のエンティティを追加し、最後に変更を保存すると、DbContextはObjectContextの3〜5倍遅くなります(ところで:大量のエンティティを追加する方がSqlBulkCopyを使用した方が良いことを知っていますが、それはポイントではありません)。追加するたびに変更を保存すると、DbContextの速度は2倍近く遅くなります。削除に関してはさらに悪化します。すべてのエンティティの削除の最後に保存すると、DbContextはObjectContextの約18倍遅くなります。

データベースアクセステクノロジーと小さなコンソールアプリケーションを比較してダブルチェックするために使用する、高度に開発されたテストアプリケーションを使用しました。どちらも、DbContextを使用してエンティティを追加および削除すると、悪い結果を示しました。コンソールアプリケーションの結果は次のとおりです。

Inserting 2000 entities via DbContext saving changes at the end: 2164ms
Inserting 2000 entities via ObjectContext saving changes at the end: 457ms
Inserting 2000 entities via DbContext saving changes after each object addition: 8420ms
Inserting 2000 entities via ObjectContext saving changes after each object adding: 4857ms
Inserting 2000 entities via DbContext using a new DbContext for each object addition: 4018ms
Deleting 2000 entities via DbContext saving changes at the end: 4794ms
Deleting 2000 entities via ObjectContext saving changes at the end: 261ms
Deleting 2000 entities via DbContext saving changes after each object deletion: 25536ms
Deleting 2000 entities via ObjectContext saving changes after each object deletion: 2110ms

VC 2010およびVS 11のEF 5.0 Beta 2でEF 4.3を使用して、ほぼ同じ結果を得ようとしました。 「EF#4.x DbContext Generator for C#」および「EF 5.x DbContext Generator for C#」。

何が間違っているのでしょうか?テスト結果によると、エンティティを追加または削除する必要のあるアプリケーションでDbContextを使用することはありません(残念ながらDbContextは使用できなくなります)。

Webサーバーにコンソールテストアプリケーションを配置します: EF 4.3 DbContext TestEF 5.0 DbContext Test

どんなアイデア/修正も大歓迎です。

46
Jürgen Bayer

これをDbContextテストに追加してみてください:

dbContext.Configuration.AutoDetectChangesEnabled = false;

// Now do all your changes

dbContext.ChangeTracker.DetectChanges();
dbContext.SaveChanges();

そして、テストを再度実行してください。

コンテキストからAddAttach、またはDeleteを使用するたびにエンティティの変更をチェックするDbContext APIにアーキテクチャ上の変更がいくつかありました。 ObjectContext APIでは、SaveChangesをトリガーしたときにのみこの検出が実行されます。最も一般的なシナリオではより良いソリューションですが、大量のデータ処理には特別な処理が必要です。

91
Ladislav Mrnka

EF6では、 DbSetAddRange および RemoveRange を使用できるようになりました。

リンクのドキュメントから:

AutoDetectChangesEnabledがtrue(デフォルト)に設定されている場合、エンティティを{追加、削除}する前にDetectChangesが1回呼び出され、再度呼び出されることはありません。これは、状況によっては、{Add、Remove} Rangeが{Add、Remove}を複数回呼び出すよりも大幅にパフォーマンスが向上する可能性があることを意味します。

14
Andreas Warberg