プロジェクトの記事を更新するために使用しているUpdate
メソッドがリポジトリにあります。私は当初、記事の管理者編集を実行するためだけにこの方法を使用していました。それは正しく処理されますが、「最も読まれた」記事を計算するための簡単なメカニズムを追加することにしました。TimesRead
そのためには、記事が表示されるたびにプロパティを更新したいと考えています。これにより、 の使用を中心に展開しているように見える更新で問題が発生していますObjectStateManager.ChangeObjectState
。これが私のUpdate
方法です:
public void Update(Article article)
{
if (article == null) return;
db.Articles.Attach(article);
db.ObjectStateManager.ChangeObjectState(article, EntityState.Modified);
db.SaveChanges();
}
私AdminController
の次のメソッドは正しく更新されます:
[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);
これを解決するために何ができるかを見て回った後、このSOの質問に対する答えに出くわしました。Update
そのため、メソッドを提案されたコードに置き換えることで、その答えを実装しました。これは、私の管理シナリオでも正しく機能しますが、TimesRead
シナリオでは機能しません。次の例外がスローされます。
同じキーを持つオブジェクトが ObjectStateManager に既に存在します。ObjectStateManager は、同じキーを持つ複数のオブジェクトを追跡できません。
例外の意味は非常に明確ですが、このような単純な更新をどのように処理すればよいのか疑問に思います。EntityState.Unchanged
私は、設定によってモデルが変更されていないと考えるようにEFを「騙す」ことができることを発見しましTimesRead
たObjectStateManager
。
また、これらのシナリオがどのように異なるかは明らかです。このアクションは、ViewModel のプロパティをアタッチされていない新しいオブジェクトにEdit
マッピングしますが、コンテキストから直接取得したオブジェクトを処理します。そのため、これらのコントローラー メソッドの 1 つをリファクタリングして、更新の手順を同じにする必要があると感じています。両方のアプローチが共存できるように見えるので、どのようにアプローチする必要があるのか よくわかりません。私の質問は、両方のタイプの更新が正しく機能するようにするには、何を変更すればよいですか?Article
ArticleController
お時間をいただきありがとうございます。投稿されたコードの量については本当に申し訳ありません。私はそれがすべて問題に関連していると感じています。