自分のプロジェクトの記事を更新するために私のリポジトリにUpdate
メソッドがあります。私は当初、記事の管理編集を実行するためだけにこの方法を使用していました。それは正しく処理されますが、私は「最も読まれた」記事を計算するための簡単なメカニズムを追加したいと考えました。これを行うために、記事を閲覧するたびにTimesRead
のプロパティを更新したいと思います。これは、ObjectStateManager.ChangeObjectState
を使用して周りを回っているように見えるアップデートで私に問題を与えています。ここに私のUpdate
方法です:私のAdminController
でMVC3:リポジトリのアップデートとObjectStateManager
public void Update(Article article)
{
if (article == null) return;
db.Articles.Attach(article);
db.ObjectStateManager.ChangeObjectState(article, EntityState.Modified);
db.SaveChanges();
}
は、以下の方法が正しく更新されます
[HttpPost]
public ActionResult Edit(AdminEditViewModel viewModel)
{
if (ModelState.IsValid)
{
Article article = Mapper.Map<AdminEditViewModel, Article>(viewModel);
articleRepository.Update(article);
return RedirectToAction("Index");
}
viewModel.Categories = new SelectList(categoryRepository.GetAll(), "CategoryID", "Name", viewModel.CategoryID);
return View(viewModel);
}
しかし、TimesRead
シナリオでは、更新がの例外トリガします:
オブジェクトがすでにオブジェクトコンテキスト内にあるため、オブジェクトを追加できません。オブジェクトは、変更されていない状態のときにのみ再接続できます。そのコントローラのメソッドから
関連するコードは:
var model = articleRepository.GetByID(id);
model.TimesRead++;
articleRepository.Update(model);
return View(model);
私はこれを解決するために何ができるかを確認するために周りを見た後、私はthis SOの質問に答えに出くわしました。そこで私はUpdate
メソッドをコードを提案したものに置き換えてその答えを実装しました。これは私の管理シナリオでは正しく動作しますが、TimesRead
シナリオでは正しく動作しません。次の例外がスローされます。
ObjectStateManagerに同じキーを持つオブジェクトがすでに存在します。 ObjectStateManagerは、同じキーを持つ複数のオブジェクトを追跡できません。
例外は意味がはっきりしていますが、私はこれらのような簡単なアップデートをどのように扱うべきか疑問に思っています。私は、EntityState.Unchanged
を設定してモデルが変更されずにTimesRead
に更新されますが、ObjectStateManager
にオブジェクトへの参照が保持されていないことを示す管理者の更新は例外であるとEFを "欺く"ことができます。
これらのシナリオがどのように異なっているかは明らかです。 Edit
アクションは、ViewModelのプロパティを新しい添付されていないArticle
オブジェクトにマッピングしますが、ArticleController
はコンテキストから直接取得されたオブジェクトを処理します。それは、私がそれらのコントローラメソッドの1つをリファクタリングする必要があるという気持ちで私を残すので、更新するために取られたステップは同じです。私は両方のアプローチが私に共存できるように見えるので、どのようにアプローチしなければならないのかは分かりません。だから私の質問は、正しく動作するように両方のタイプのアップデートを取得するために何を変更できますか?
あなたのお時間をいただきありがとうございます。投稿されたコードの量は本当に申し訳ありません。私はそれがすべて問題に関連していると感じています。
DBコンテキストをどのようにインスタンス化していますか?あなたの更新メソッドはそれをやっていないようです。 –
これは 'ArticleRepository'クラス内のプライベートメンバーなので、リポジトリが構築されるとすぐにインスタンス化されます。 'ArticleRepository.Update'は問題のメソッドです。申し訳ありませんが、私はそれを十分に明確にしませんでした。 –
そして、どのようにあなたのArticleRepositoryを構築していますか?私の指摘は、HTTPはステートレスなので、要求を越えてDBコンテキストへの参照を保持することはできません。だから、あなたの問題がdbコンテキストの古いコピーによって引き起こされていないことを確認しています。 –