私はこれに従い ました MVC Createビューでの多対多の関係データの保存
これは、私の多くの値を多くの値に追加するために機能します。
しかし、同じコードを使用して編集しようとすると、何をしても、多対多の値は変更されません。
私のシナリオは...
メニューとページがあります。
多くのメニューに多くのページを追加できます。
問題のメニューにページを完全に追加しますが、編集時に Menu.Pages.Clear(); を呼び出しても、毎回同じ値になります。Context.SaveChanges(); メニューに関連付けられたページ リストの編集前と同じ値になるだけです。
[HttpPost]
public ActionResult Edit(MenuViewModel MenuViewModel, int PageID, int ActivePosition, int OldAP)
{
Service.AddOrUpdateCourses(MenuViewModel.ZMenu, MenuViewModel.Pages);
ViewBag.Message = Service.CreateOrUpdate<ZMenu>(MenuViewModel.ZMenu, PageID, ActivePosition, OldAP);
if (ViewBag.Message.ToString() == "true")
{
Service.Commit();
return RedirectToAction("Index");
}
ViewBag.ActivePosition = ModuleManager.AvailableModulePositions(OldAP);
ViewBag.PageID = Service.GetPageSelectList(MenuViewModel.ZMenu.Page.ID);
return View(MenuViewModel);
}
PageID はモジュール (メニュー) が配置されているページ、ActivePosition はモジュールの位置、OldAP は更新前の位置です。これはコードの一般的なテーマであり、他の関数との混乱を防ぐためです。
サービスはリポジトリです。
public void AddOrUpdateCourses(ZMenu ZMenu, IEnumerable<AssignedPageData> AssignedPages)
{
ZMenu.Pages.Clear();
foreach (var AssignedPage in AssignedPages)
{
if (AssignedPage.Assigned)
{
var newpage = Context.ZPages.Find(AssignedPage.ID);
Context.ZPages.Attach(newpage);
ZMenu.Pages.Add(newpage);
}
}
}
役に立たない可能性のある情報...使用される他の方法....
public string CreateOrUpdate<T>(object _Module, int PageID, int ActivePosition, int OldAP = -1)
{
Type type = typeof(T);
dynamic Module = type.DynamicCast(_Module);
// set the date, depending on if its a create or edit
if (Module.ID == 0 || Module.ID == null)
Module.Date = DateTime.Now;
else
{
int ID = Module.ID;
Module.Date = Context.ZModules.AsNoTracking().Single(x => x.ID == ID).Date;
}
Module.Type = Context.ZModuleTypes.Single(x => x.Name == type.Name.Substring(1, type.Name.Length - 1));
Module.Page = Context.ZPages.Single(x => x.ID == PageID);
Module.ActivePosition = ActivePosition;
bool PositionTaken = false;//this.CheckModulePositions<T>(_Module, OldAP);
if (PositionTaken)
{
return "Position " + Module.ActivePosition + " is taken, please select another";
}
else
{
try
{
int ID = Module.ID ?? -1;
if (Context.ZModules.AsNoTracking().Where(x => x.ID == ID).Count() == 0)
{
Context.Entry(Module).State = System.Data.EntityState.Added;
}
else
{
Context.Entry(Module).State = System.Data.EntityState.Modified;
}
return "true";
}
catch (Exception ex)
{
return ex.Message;
}
}
}
モジュールの位置保護 (モジュールの位置ごとに 1 つのモジュール) を無効にして、それが潜在的な問題になるのを防ぎましたが、それは修正されていませんでした。
これをデバッグしたところ、Commit() メソッドが呼び出されると、ZMenu エンティティには問題の正しいページがありますが、その後、ページ リストは編集前の状態に戻ります。作成時に機能します。
誰にも手がかりがありますか?
必要に応じてさらに情報を提供します。
編集:
これが問題のViewModelです...
public class MenuViewModel
{
public ZMenu ZMenu { get; set; }
public virtual ICollection<AssignedPageData> Pages { get; set; }
public MenuViewModel(ZMenu ZMenu)
{
this.ZMenu = ZMenu;
}
public MenuViewModel()
{
}
}
編集2:
以下のコメントといくつかの継続的な作業により、コードは次のようになりました。問題のある領域と思われる部分で、エラーが発生しましたが、エラーを修正する方法がわかりません。
Store update、insert、または delete ステートメントが予期しない数の行 (0) に影響を与えました。エンティティが読み込まれてから、エンティティが変更または削除された可能性があります。ObjectStateManager エントリを更新します。
public void AddOrUpdateCourses(ZMenu ZMenu, IEnumerable<AssignedPageData> AssignedPages)
{
Context.ZMenuModules.Attach(ZMenu);
HashSet<int> CurrentPages = new HashSet<int>
(ZMenu.Pages.Select(i => i.ID));
foreach (var AssignedPage in AssignedPages)
{
ZPage newpage = Context.ZPages.Find(AssignedPage.ID);
Context.ZPages.Attach(newpage);
if (AssignedPage.Assigned)
{
if (!CurrentPages.Contains(AssignedPage.ID))
{
ZMenu.Pages.Add(newpage);
}
}
else
{
if (CurrentPages.Contains(AssignedPage.ID))
{
ZMenu.Pages.Remove(newpage);
}
}
}
}
Context.SaveChanges() が呼び出されると、エラーが発生します。
編集3:
ご覧のとおり、これは現在部分的に回答されています。
複数のオブジェクトが追跡されているというエラーを発生させずに ZMenu.Pages の値を更新する方法を教えてください。