3

50 万を超えるレコードを含むテーブルがあります。各レコードには約 60 のフィールドが含まれていますが、そのうちの 3 つだけを変更します。

計算とルックアップに基づいて、各エンティティに小さな変更を加えます。

明らかに、各エンティティを順番に更新することはできません。そうするとSaveChanges、時間がかかりすぎるためです。

そのため、プロセス全体の最後SaveChangesContext.

これにより、適用時にメモリ不足エラーが発生しますSaveChanges

私は DataRepository パターンを使用しています。

//Update code
DataRepository<ExportOrderSKUData> repoExportOrders = new DataRepository<ExportOrderSKUData>();
foreach (ExportOrderSKUData grpDCItem in repoExportOrders.all())
{
  ..make changes to enity..
}
repoExportOrders.SaveChanges();



//Data repository snip
public DataRepository()
{
  _context = new tomEntities();
  _objectSet = _context.CreateObjectSet<T>();
}
public List<T> All()
{
  return _objectSet.ToList<T>();
}
public void SaveChanges()
{
  _context.SaveChanges();
}

この場合、何を探すべきですか?

4

1 に答える 1

4

1 つのトランザクション内で EF を介して 50 万件のレコードを変更することは想定されていません。小さなバッチでそれを行うことは、より優れた技術的解決策です。いくつかのストアドプロシージャを介してデータベース側でそれを行うと、さらに優れたソリューションになる可能性があります。

コードを少し変更することから始めます (自分でリポジトリ API に変換します)。

using (var readContext = new YourContext()) {
    var set = readContext.CreateObjectSet<ExportOrderSKUData>();

    foreach (var item in set.ToList()) {
       readContext.Detach(item);
       using (var updateContext = new YourContext()) {
          updateContext.Attach(item);
          // make your changes
          updateContext.SaveChanges();
       }
    }
}

このコードはアイテムの保存に別のコンテキストを使用します = 各保存は独自のトランザクション内にあります。それを恐れないでください。EFの 1 回の呼び出しでより多くのレコードを保存しようとしても、SaveChanges更新されたレコードごとにデータベースへの個別のラウンドトリップが使用されます。唯一の違いは、同じトランザクションで複数の更新を行いたい場合です (ただし、1 つのトランザクションで 50 万回の更新を行うと問題が発生します)。

別のオプションは次のとおりです。

using (var readContext = new YourContext()) {
    var set = readContext.CreateObjectSet<ExportOrderSKUData>();
    set.MergeOption = MergeOption.NoTracking;

    foreach (var item in set) {
       using (var updateContext = new YourContext()) {
          updateContext.Attach(item);
          // make your changes
          updateContext.SaveChanges();
       }
    }
}

これは、実行する前にすべてのエンティティをロードする必要がないため、理論的にはさらに少ないメモリを消費する可能性がありますforeachToList最初の例では、呼び出し時の例外 (列挙中にコレクションを変更する) を回避するために、列挙の前にすべてのエンティティを ( を呼び出すことによって) ロードする必要がある可能性がありますDetachが、それが実際に起こるかどうかはわかりません。

これらの例をいくつかのバッチを使用するように変更するのは簡単です。

于 2013-04-11T07:39:28.483 に答える