3

Excel スプレッドシートをインポートし、データをデータ オブジェクトに解析するプロセスがあります。スプレッドシート ベースのデータ管理から、有効なデータをチェックする管理されたデータベース システムに顧客を移行しているため、このデータのソースは非常に疑わしいものです。

インポート プロセス中に、データの基本的なサニティ チェックをいくつか実行して、インポートするデータがどれほど悪いかを調整しますが、全体的な検証は DbContext で実行します。

私がやろうとしていることの一部は、ファイルをインポートするために何を修正する必要があるかを簡単に判断できるように、スプレッドシートにデータが悪いという行番号を提供したいということです。

スプレッドシートからのデータ( )modelと、データベースからの商談( ) を取得したらopp、プロセスの疑似コードを次に示します。

foreach (var model in Spreadsheet.Rows) { // Again, pseudocode
    if(opp != null && ValidateModel(model, opp, row)) {
        // Copy properties to the database object

        // This is in a Repository-layer method, not directly in my import process.
        // Just written here for clarity instead of several nested method calls.
        context.SaveChanges(); 
    }
}

必要に応じて、ここでさらに多くのコードを提供できますが、問題は DbContext のValidateEntity()メソッド (DbContext のオーバーライド) にあります。

context繰り返しますが、私が知る限り、私が書いたコードに問題はありませんが、このレベルの検証に失敗した Opportunity は、保存されていないオブジェクトの一部として残ります。ValidateEntity()が呼び出されるたびに検証されます。これにより、最初の問題が発生した後、すべての行で同じ検証エラー メッセージが繰り返されます。

[編集]一度検証に失敗した後、コンテキストがオブジェクトの検証を試みないようにする方法はありますか[編集]? 最後まで待って、最後にcontext.SaveChanges()1 回呼び出してこれを回避できることはわかっていますが、これをデータベース内の行と一致させたいと考えています。

参考までに、Code First アプローチで Entity Framework 6.1 を使用しています。

EDIT Marc L.のためにさらに明確化を試みています(上記のコードブロックの更新を含む)

現在、私のプロセスは、スプレッドシートにある行と同じ数の行を反復処理します。一度だけ呼び出すアプローチではなく、保存するオブジェクトごとにリポジトリ レイヤーを呼び出す理由context.SaveChanges()は、検証エラーの原因となっている行を特定できるようにするためです。

私の DbContext のカスタムValidateEntity()メソッドが検証エラーをキャッチしていることを嬉しく思いますが、問題はDbEntityValidationException、同じエンティティに対して複数回スローしていないという事実にあります。

context.SaveChanges()オブジェクトが検証に 1 回失敗すると、コンテキストが呼び出された回数に関係なく、オブジェクトを保存しようとしなくなります。

4

1 に答える 1

1

あなたの質問はだまされていません(これはエンティティをロードするのではなく、保存することに関するものです)が、上記のジミーのアドバイスに従うことができます。つまり、エンティティがコンテキストに追加されると、「追加済み」状態で追跡され、再検証を停止する唯一の方法は、エンティティをデタッチすることです。これは SO 内部リンクですが、コード スニペットを再現します。

dbContext.Entry(entity).State = EntityState.Detached;

ただし、不必要に状態を管理するために例外を使用しているため、それはあなたが望む方法ではないと思います (例外は非常に高価であることで有名です)。

与えられた情報に基づいて、よりセットベースのソリューションを使用します。

  • 元のスプレッドシートの行を記録する RowID が含まれるようにモデル クラスを変更します (これを使用する正当な理由は他にもあると思われます)。
  • コンテキストのエンティティ追跡をオフにします (それぞれAdd()が O(1) になるようにする変更検出のターン)
  • すべてのエンティティを追加
  • 呼び出しcontext.GetValidationErrors()て、前述の RowID を使用して無効な行を特定し、一度にすべてのエラーを取得します。

プロセスが適切な行を保存するか、ファイル全体を拒否する必要があるかを示していませんでしたが、これはどちらにも対応します。つまり、適切な行を保存する必要がある場合は、上記のコードを使用してすべての無効な行を切り離し、それからSaveChanges()


最後に、適切な行を保存したいが、セットベースの方法が気に入らない場合は、DbContext行ごとに new を使用するか、少なくともDbContext各エラーの後に new を作成することをお勧めします。ADO.NET チームは、コンテキストの作成は「比較的安価」であると主張しているため (これについての引用や統計が手元になくて申し訳ありません)、これによってスループットが大きく損なわれることはありません。それでも、少なくとも O(n) のままです。大規模なコンテキストを管理すると、他の問題も発生する可能性があります。

于 2014-06-03T05:31:57.137 に答える