0

私はこれに従い ました 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 の値を更新する方法を教えてください。

4

3 に答える 3

0

最終的には、Microsoftのチュートリアルに従って修正しました。

同じ状況なので、問題が発生した場合は、質問の上部にあるリンクを見ている人は、代わりにこれに従うことをお勧めします。

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-応用

(一番下のスクリーンショットは私がやろうとしていたことです)

于 2012-08-31T23:40:10.530 に答える
0

EF Code First を使用して多対多のシナリオでレコードを作成 / 更新 / 削除する方法を詳しく説明したブログ投稿をいくつか書きました。投稿には完全な解決策も添付されているので、うまくいけば、あなたまたはこれを読んでいる他の誰かが役に立つと思います. これは 3 番目の最後の部分です。

MVC4 で多対多のデー​​タを保存する

于 2013-04-19T07:36:29.617 に答える
0

問題が見つかりました。

デバッグ時に、編集が機能しない場合でも、問題の ZMenu のリストにページがまったくないことに気付きました。だから、これは間違っています。(編集が存在する前に)。

そこで、HttpPost 編集アクションに渡されたモデルの ID を使用してコンテキストから ZMenu を「検索」し、以前の「ViewModel.ZMenu」の代わりにこれを使用しました。

これにより、ZMenu には本来あるべき 1 ページが作成されました。これにより、プログラムの問題が修正され、編集が成功するはずです。

于 2012-08-31T21:11:17.713 に答える