问题更新瓦特/ EF4回购和放大器; MVC2 - 无法更新多到许多图形 [英] Problems updating w/ EF4 repo & MVC2 - can't update many-to-many graph

查看:119
本文介绍了问题更新瓦特/ EF4回购和放大器; MVC2 - 无法更新多到许多图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎无法使用EF4在MVC2成功更新一个多到很多图形。我想这样做将是晴()整个图形,调用调用SaveChanges(),然后在最后再次重建图形调用调用SaveChanges()最简单的事情,但它不工作。我的所有其他属性的的工作,但是。首先,我的操作方法:

I can't seem to successfully update a many-to-many graph in MVC2 using EF4. I figured the simplest thing to do would be to Clear() the entire graph, call SaveChanges(), then rebuild the graph calling SaveChanges() again at the end, but it's not working. All my other properties ARE working, however. First, my Action Methods:

    public ActionResult EditReview(int id)
    {
        var game = _gameRepository.GetGame(id);
        var genres = _gameRepository.AllGenres();
        var platforms = _gameRepository.AllPlatforms();

        var model = new AdminGameViewModel { GameData = game, AllGenres = genres, AllPlatforms = platforms }; 

        return View(model);
    }

    //
    // POST: /Admin/EditReview/5

    [HttpPost]
    public ActionResult EditReview([Bind(Prefix="GameData")]Game existingGame, int[] PlatformIDs)
    {
        try
        {
            _gameRepository.ValidateGame(existingGame, PlatformIDs);
        }
        catch(RulesException ex)
        {
            ex.CopyTo(ModelState);
            ex.CopyTo(ModelState, "GameData");
        }

        if (ModelState.IsValid)
        {
            return RedirectToAction("Index");
        }
        else
        {
            var genres = _gameRepository.AllGenres();
            var platforms = _gameRepository.AllPlatforms();

            var model = new AdminGameViewModel { GameData = existingGame, AllGenres = genres, AllPlatforms = platforms };

            return View(model);
        }
    }

回购自身(ValidateGame和游戏存档的相关方法):

The repo itself (ValidateGame and SaveGame are the relevant methods):

namespace HandiGamer.Domain.Concrete
{
    public class HGGameRepository : IGameRepository
    {
        private HGEntities _siteDB = new HGEntities();

        public List<Game> Games
        {
            get { return _siteDB.Games.ToList(); }
        }

        public void ValidateGame(Game game, int[] PlatformIDs)
        {
            var errors = new RulesException<Game>();

            if (string.IsNullOrEmpty(game.GameTitle))
            {
                errors.ErrorFor(x => x.GameTitle, "A game must have a title");
            }

            if (string.IsNullOrEmpty(game.ReviewText))
            {
                errors.ErrorFor(x => x.ReviewText, "A review must be written");
            }

            if (game.ReviewScore <= 0 || game.ReviewScore > 5)
            {
                errors.ErrorFor(x => x.ReviewScore, "A game must have a review score, and the score must be between 1 and 5");
            }

            if (string.IsNullOrEmpty(game.Pros))
            {
                errors.ErrorFor(x => x.Pros, "Each game review must have a list of pros");
            }

            if (string.IsNullOrEmpty(game.Cons))
            {
                errors.ErrorFor(x => x.Cons, "Each game review must have a list of cons");
            }

            if (PlatformIDs == null || PlatformIDs.Length == 0)
            {
                errors.ErrorForModel("A game must belong to at least one platform");
            }

            if (game.GenreID == 0)
            {
                errors.ErrorFor(x => x.GenreID, "A game must be associated with a genre");
            }

            if (errors.Errors.Any())
            {
                throw errors;
            }
            else
            { 
                SaveGame(game, PlatformIDs);
            }
        }

        public void SaveGame(Game game, int[] PlatformIDs)
        {
            _siteDB.Games.Attach(game);

            if (game.GameID > 0)
            {
                _siteDB.ObjectStateManager.ChangeObjectState(game, System.Data.EntityState.Modified);

                game.Platforms.Clear();
            }
            else
            {
                _siteDB.ObjectStateManager.ChangeObjectState(game, System.Data.EntityState.Added);
            }

            foreach (int id in PlatformIDs)
            {
                Platform plat = _siteDB.Platforms.Single(pl => pl.PlatformID == id);
                game.Platforms.Add(plat);
            }

            game.LastModified = DateTime.Now;

            _siteDB.SaveChanges();
        }

        public Game GetGame(int id)
        {
            return _siteDB.Games.Include("Genre").Include("Platforms").SingleOrDefault(g => g.GameID == id);
        }

        public IEnumerable<Game> GetGame(string title)
        {
            return _siteDB.Games.Include("Genre").Include("Platforms").Where(g => g.GameTitle.StartsWith(title)).AsEnumerable<Game>();
        }

        public List<Game> GetGamesByGenre(int id)
        { 
            return _siteDB.Games.Where(g => g.GenreID == id).ToList();
        }

        public List<Game> GetGamesByGenre(string genre)
        {
            return _siteDB.Games.Where(g => g.Genre.Name == genre).ToList();
        }

        public List<Game> GetGamesByPlatform(int id)
        {
            return _siteDB.Games.Where(g => g.Platforms.Any(p => p.PlatformID == id)).ToList();
        }

        public List<Game> GetGamesByPlatform(string platform)
        {
            return _siteDB.Games.Where(g => g.Platforms.Any(p => p.Name == platform)).ToList();
        }

        public List<Genre> AllGenres()
        {
            return _siteDB.Genres.OrderBy(g => g.Name).ToList();
        }

        public List<Platform> AllPlatforms()
        { 
            return _siteDB.Platforms.OrderBy(p => p.PlatformID).ToList();
        }
    }
}

我难倒。

推荐答案

凯文,
哦,这是一个有点复杂,并迫使你回EFv1模式,因为采用M:M你没有外键倚着你被卡住其对象

Kevin, oh this is a little complex and forces you back to EFv1 patterns because with M:M you don't have foreign keys to lean on and you are stuck with having objects.

当你添加一个游戏,你想要的关系(即在连接表中的行)添加,但你不希望被添加的平台,因为它只是一个参考。

WHen you add a game, you do want the relationship (i.e. a row in the join table) to be added but you don't want the platform to be added since it's just a reference.

我没有实际做过,但我认为这将是更容易,如果你能打散它,然后重建平台收集一旦游戏连接并标明添加。否则,如果您添加整个图形,一切都被打上补充说。

I haven't actually done this but I think it would be easier if you could break it apart and then rebuild the platforms collection once the game is attached and marked added. Otherwise if you add the whole graph, everything gets marked added.

与EF问题是,如果附加游戏,你将获得附加太相关的东西。有可能是一个更清洁的模式,但我的想法是从游戏中分离平台,游戏重视的背景下,将其标记为补充。然后我会附上平台的上下文。他们将保持不变。然后将它们添加到games.platform集合。该平台将仍然不变,但的可以理解的。

Problem with EF is that if you attach game you will get the related stuff attached too. There might be a cleaner pattern but my thought is to detach the platforms from the game, attach the game to the context, mark it as added. Then I would attach the platforms to the context. They will be "unchanged". Then add them to the games.platform collection. The platforms will still be unchanged but the : will be understood.

您可能已经试过了。我必须做我自己,看着一切的实体状态,因为我一起去看看肯定发生了什么。关键是,EF需要跟踪一个的 的已添加的关系,这是新的(并会导致所添加的连接表中的行),但了解的平台不是新的。

You may have tried that. I'd have to do it myself and watch the entity state of everything as I go along to see for sure what's happening. The key is that EF needs to track that a relationship has been added and that's new (and will result in a row in the join table being added) but understand that Platforms are not new.

心连心
朱莉

这篇关于问题更新瓦特/ EF4回购和放大器; MVC2 - 无法更新多到许多图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆