在实体框架中编辑多对多。可以添加但不能删除

时间:2016-01-23 21:08:57

标签: c# asp.net-mvc entity-framework entity-framework-5

在我的POST编辑功能中,我的viewmodel包含我想要更新的游戏以及我想要添加到游戏中的platformId列表。

使用此代码,我能够为我的游戏添加平台,但无法删除它们。我在最后放了一个断点,肯定看到viewModel.Game.Platforms只有我选择但我的游戏列表中没有更新。

如果我添加一些平台并同时删除一些平台。添加了新平台,但没有删除。

public ActionResult Edit(GameViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        List<Platform> platforms = new List<Platform>();
        foreach (var id in viewModel.PostedPlatforms.PlatformIds)
        {
            platforms.Add(db.Platforms.Find(Int32.Parse(id)));
        }
        db.Games.Attach(viewModel.Game);
        viewModel.Game.Platforms = platforms;
        db.Entry(viewModel.Game).State = EntityState.Modified;
        UpdateModel(viewModel.Game);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(viewModel.Game);
}

模型类是

public class Game
{
    public int GameId { get; set; }

    public string Title { get; set; }

    public List<Platform> Platforms { get; set; }
}

public class Platform
{
    public int PlatformId { get; set; }

    public string Name { get; set; }

    public List<Game> Games { get; set; }
}

使用我们的mandave的建议,我得到了这个代码,虽然它确实改变了平台选择,但它每次都会创建一个新的游戏条目效率低下,并且还会增加内容的ID,从而弄乱书签。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(GameViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        List<Platform> platforms = new List<Platform>();
        if(viewModel.PostedPlatforms != null)
        {
            foreach (var id in viewModel.PostedPlatforms.PlatformIds)
            {
                platforms.Add(db.Platforms.Find(Int32.Parse(id)));
            }
        }
        db.Games.Remove(db.Games.Find(viewModel.Game.PostId));
        db.SaveChanges();
        viewModel.Game.Platforms = platforms;
        db.Games.Add(viewModel.Game);

        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(viewModel.Game);
}

2 个答案:

答案 0 :(得分:1)

你可以试试这个......

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(GameViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        List<Platform> selectedPlatforms = viewModel.Select(pl => GetPlatformById(pl.Id)).ToList();
        var game = GetGameById(viewModel.Id);

        UpdateGamePlatforms(game, selectedPlatforms);

        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(viewModel.Game);
    }        



private Platform GetPlatformById(int platformId)
{
    return db.Platforms.First(pl => pl.Id == platformId);
}

private Game GetGameById(int gameId)
{
    return db.Games.First(g => g.Id == gameId);
}

private void UpdateGamePlatforms(Game game, IList<Platform> selectedPlatforms)
{
    var gamePlatforms = game.Platforms.ToList();

    foreach (var gamePlatform in gamePlatforms)
    {
        if (selectedPlatforms.Contains(gamePlatform) == false)
        {
            game.Platforms.Remove(gamePlatform);
        }
        else
        {
            selectedPlatforms.Remove(gamePlatform);
        }
    }

    game.Platforms.AddRange(selectedPlatforms);
}

UpdateGamePlatforms将从游戏中移除不再选择的平台。它将离开仍然被选中的平台,并且还将为已经选择的游戏添加新的平台。

答案 1 :(得分:0)

解决方案:使用TomJerrum的解决方案,我现在可以正确编辑平台列表。要更新其余的属性,我必须映射游戏对象的所有属性,我试图编辑以匹配我的viewModel的属性。值得庆幸的是,已经有了一个函数,所以我只需要添加db.Entry(游戏).CurrentValues.SetValues(viewModel.game);.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(GameViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        List<Platform> selectedPlatforms = new List<Platform>();

        if (viewModel.PostedPlatforms != null)
        {
            int[] platformIds = Array.ConvertAll(viewModel.PostedPlatforms.PlatformIds, p => Convert.ToInt32(p));

            selectedPlatforms.AddRange(db.Platforms.Where(item => platformIds.Contains(item.PlatformId)).ToList());
        }

        var game = GetGameById(viewModel.Id);

        UpdateGamePlatforms(game, selectedPlatforms);

        db.Entry(game).CurrentValues.SetValues(viewModel.game);

        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(viewModel.Review);
}

private Game GetGameById(int gameId)
{
    return db.Games.First(g => g.Id == gameId);
}

private void UpdateGamePlatforms(Game game, IList<Platform> selectedPlatforms)
{
    var gamePlatforms = game.Platforms.ToList();

    foreach (var gamePlatform in gamePlatforms)
    {
        if (selectedPlatforms.Contains(gamePlatform) == false)
        {
            game.Platforms.Remove(gamePlatform);
        }
        else
        {
            selectedPlatforms.Remove(gamePlatform);
        }
    }

    game.Platforms.AddRange(selectedPlatforms);
}