5

私は EF5 Code First を使用しており、テーブルをすばやくクリアする方法が必要でした。したがって、私は ExecuteSqlCommand を使用してテーブルを高速にクリアするための非常に簡単な方法を作成しました。コードは以下のとおりです。

    public void FastClearTable(Type tableType)
    {
        Context.Database.ExecuteSqlCommand(
            string.Format("delete from {0}", PluraliseTableName(tableType.Name)));
    }

これを使用して、再計算する前にテーブルをクリアします。以下に、私の方法の簡略化されたバージョンをリストしました。テーブルのキーは文字列 (つまり、ID キーではない) であるため、ExecuteSqlCommand によって削除されたエントリと同じキーを持つ新しいエントリを入れていることに注意してください。

public int ComputeNewTableContent( IRepository<MyClass> rep, IUnitOfWork uow)
{
     if ( rep.GetUntracked().Count() > 0)
           uow.FastClearTable( typeof(MyClass));

     --- compute new entries and call rep.Insert( newEntry) for each one ---
     uow.Commit();    //This calls DbContext.SaveChanges()
}

これは最初は問題なく動作しますが、もう一度実行すると、uow.Commit() によって呼び出される SaveChanges() コマンドで例外が発生します。例外は次のとおりです。

Message="呼び出しのターゲットによって例外がスローされました。"

InnerException Message="データベースへの変更は正常にコミットされましたが、オブジェクト コンテキストの更新中にエラーが発生しました。ObjectContext は矛盾した状態である可能性があります。内部例外メッセージ:オブジェクトのキー値が別のオブジェクトと競合しているため、AcceptChanges を続行できませんObjectStateManager. AcceptChanges を呼び出す前に、キー値が一意であることを確認してください。」

このアーカイブされた MSDN投稿を見つけた場合、その人は同じ問題を抱えていましたが、答えはありませんでした。私の見解では、データのメモリ バージョンはまだ存在しており、ExecuteSqlCommand については認識していません。ただし、EFについてはまだ修正方法を知るのに十分な知識がありません。

もちろん、「通常の」削除を使用して回避できますが、何が起こっているのか、どのように処理できるのかを説明していただければ幸いです。これにより、Entity Framework に関する私の知識が向上します。

前もって感謝します。

4

2 に答える 2

5

Julia Lerman の優れた本'Programming Entity Framework: DbContext'に出会うまで、エンティティ フレームワークで ExecuteSqlCommand を安全に使用することに関する私の質問に対する適切な答えが見つかりませんでした。

彼女は ExecuteSqlCommand の使用 (226 ページ) について説明していますが、最も重要なことは、 ExecuteSqlCommand の後にReloadコマンドを使用してローカルを更新することについて言及しています (138 ページ)。これにより、データベースからメモリ内エンティティが更新されます。次のように使用します。

    yourDbContext.Entry(TheTrackedEntityYouWantToUpdate).Reload();

これはまさに私が必要としていたものです。ありがとうジュリア。

私の意見では、Julia Lerman の DbContext の本は、Code First を使用して実際のアプリケーションを計画している人にとって必読です。

于 2013-02-16T11:23:47.630 に答える
0

キーに ID を使用していますか? ObjectContext が、データベースから削除した古いエンティティを追跡し、新しいエンティティを追加している可能性があります。新しいエンティティ (キーの ID 列がない場合) には、古いエンティティで使用されていたのと同じキーが与えられます。コンテキストはすでに古いエンティティを追跡しているため、追跡されたエンティティのキ​​ーを持つ新しいエンティティを取得します。EF は、すべての変更がデータベースからではなく、オブジェクト コンテキストを介して行われることを前提としています。このようなエンティティを削除する場合は、おそらくコンテキストを破棄する必要があります

于 2012-10-24T16:06:37.273 に答える