質問: _testService.GetTests(1, userId).ToList(); testList.ForEach(_obj => _uow.Tests.Delete(_obj)); _uow.Commit(); ``` 私は質問と呼ばれる質問情報を持つ別のテーブルを持っています。私は同じことをしたいと思いますが、この表には1000行以上あります。私がそれらをすべてリストして、1,000回の削除を行うと、これはあまり効率的ではありません。 この質問の削除はあまり頻繁に起こらない。どのように私はこれを行うことができるかに関して誰にでも提案があります。私は1,000回の削除をすべきですか? EFを使ってこのようなことをするのは普通ですか?
回答: 私の知る限り、EF 6はあなたのDbContextに.RemoveRange()オプションを導入しました。要するに、あなたは次のようなことをすることができます: ``` var db = new MyDbContext(); var itemsToDelete = db.MyTable.Where(x=>!x.active); db.MyTable.RemoveRange(itemsToDelete); db.SaveChanges(); ``` したがって、 `foreach`任意の型を実行する代わりに、この新しい拡張メソッドを利用することができます。あなたのUnit Of Workコンテキストでは、現在のメソッドのような単一の`Test`オブジェクトの代わりにIEnumerable(?*)を取る`Delete`メソッドのオーバーロードを持つことができます。この新しいオーバーロードは、 `RemoveRange()`関数を呼び出す必要があります。 ?* - `GetTests()`が返すものによって異なりますが、 `IEnumerable<>`は`IList<>`と`IQueryable<>`両方を対象としてい`IList<>` **編集** いくつかのコメント。まず、実際にアイテムをサービスにフェッチしたくないので、 `RemoveRange`を発行する前に`.ToList()`呼び出さないでください。これは、いくつかのパフォーマンスの時間を短縮するのに役立ちます。第二に、あなたはまあまあですが、あなたは依然として1000の削除ステートメントを発行します。ただし、パフォーマンスの向上は、 `DbSet`から削除する各アイテムのEFでChangeTrackerを呼び出さないことに起因します。 MSDNマガジンから: > AddRangeとRemoveRange前述のように、AddRangeとRemoveRangeはコミュニティメンバZorrillaからの寄稿です。各メソッドは、そのパラメータとして単一のエンティティタイプの列挙型を取ります。共有DbTransactionsセクションの最初のコードサンプルでは、Casinoインスタンスの配列を渡したときにAddRangeを使用しました。 > > context.Casinos.AddRange(new [] {casino1、casino2});これらのメソッドは、デフォルトでEntity Frameworkが各AddメソッドおよびRemoveメソッドでDetectChangesを呼び出すため、一度に1つのオブジェクトを追加または削除するよりもはるかに高速に実行されます。 Rangeメソッドを使用すると、複数のオブジェクトを処理でき、DetectChangesは1回だけ呼び出されるため、パフォーマンスが大幅に向上します。私は5,50,500,5,000、さらには5万のオブジェクトを使ってこれをテストしました。少なくとも私のシナリオでは、配列の大きさには制限がありませんでした。この改善は、オブジェクトに作用するコンテキストを取得する場合にのみ関連し、SaveChangesには関係しないことに注意してください。 SaveChangesを呼び出すと、一度に1つのデータベースコマンドしか実行されません。したがって、すぐに50,000個のオブジェクトをコンテキストに追加することができますが、SaveChangesを呼び出すと個別に実行される50,000個の挿入コマンドが得られます。実際のシステムでは実行したくないものでしょう。 > > これについては、オブジェクトをEF(bit.ly/16tMHw4)で追跡することなく、一括操作のサポートを実装し、データベースへの単一の呼び出しで複数のコマンドを一緒に送信できるようにするバッチ操作について長い議論がありました(bit.ly/PegT17)。どちらの機能も最初のEF6リリースには組み込まれていませんが、どちらも重要であり、将来のリリースに向けて予定されています。 > > 真に1つのデータベースコマンドのみを発行したい場合は、EntityFrameworkがバルクトランザクションをサポートしていないので、生のSQLステートメントを使用するストアドプロシージャのいずれかが使用できます。しかし、 `RemoveRange`項目と`AddRange`項目を使用すると(特に、あなたが言ったように、まれである場合)、foreachループで`Remove()`を呼び出すのに比べて時間が大幅に節約されます。