Проблемы с обновлением репозитория EF4 и MVC2 - не удается обновить график многие ко многим - PullRequest
0 голосов
/ 22 января 2011

Я не могу успешно обновить график многие ко многим в MVC2, используя EF4. Я подумал, что самое простое, что можно сделать, - это очистить весь график, вызвать SaveChanges (), а затем перестроить граф снова с помощью SaveChanges (), но он не работает. Все мои другие свойства ARE работают, однако. Во-первых, мои методы действий:

    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 и SaveGame являются соответствующими методами):

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();
        }
    }
}

Я в тупике.

1 Ответ

1 голос
/ 22 января 2011

Кевин, о, это немного сложно и заставляет вас вернуться к шаблонам EFv1, потому что с M: M у вас нет внешних ключей, на которые можно опереться, и вы застряли с объектами.

Когда вы добавляетев игре вы хотите, чтобы отношения (т. е. строка в таблице соединений) были добавлены, но вы не хотите, чтобы добавлялась платформа, поскольку это просто ссылка.

На самом деле я этого не делално я думаю, что было бы проще, если бы вы могли разбить ее на части, а затем заново собрать коллекцию платформ, как только игра будет прикреплена и помечена как добавленная.В противном случае, если вы добавите весь график, все будет помечено как добавленное.

Проблема с EF заключается в том, что если вы прикрепите игру, то вы также прикрепите и связанный с ней материал.Может быть, и более понятный шаблон, но я думаю, что нужно отсоединить платформы от игры, прикрепить игру к контексту, пометить ее как добавленную.Тогда я бы прикрепил платформы к контексту.Они будут "без изменений".Затем добавьте их в коллекцию games.platform.Платформы по-прежнему не изменятся, но : будет понятен.

Возможно, вы уже пробовали это.Я должен был сделать это сам и наблюдать за состоянием всего сущего, пока я иду, чтобы точно знать, что происходит.Ключ заключается в том, что EF необходимо отследить, что отношение было добавлено, и это ново (и приведет к добавлению строки в объединяемой таблице), но следует понимать, что платформы не являются новыми.

Джули

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...