Problemas para actualizar w / EF4 repo y MVC2 - no puede actualizar el gráfico muchos-a-muchos

StackOverflow https://stackoverflow.com/questions/4764370

Pregunta

Me parece que no puede actualizar correctamente un gráfico de muchos a muchos en MVC2 usando EF4. Pensé que la cosa más sencilla de hacerlo sería la de Borrar () todo el gráfico, SaveChanges llamada (), luego reconstruir los SaveChanges gráfico llamando al () de nuevo al final, pero no está funcionando. Todos mis otras propiedades SON de trabajo, sin embargo. En primer lugar, mis métodos de acción:

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

El repo sí mismo (ValidateGame y SaveGame son los métodos pertinentes):

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

Estoy perplejo.

¿Fue útil?

Solución

Kevin, Oh, esto es un poco más complejo y le obliga de nuevo a los patrones EFv1 porque con M: M no tiene claves foráneas en que apoyarse y le pegan con tener objetos

.

Cuando se agrega un juego, usted no desea que la relación (es decir, una fila en la tabla de unión) que se añade, pero no desea que la plataforma que se añade ya que es sólo una referencia.

No he hecho realmente esto, pero creo que sería más fácil si usted podría romperlo y luego reconstruir la colección de plataformas vez que el juego está unido y marcado añadido. De lo contrario, si se agrega todo el gráfico, todo se marquen añadió.

Problema con EF es que si adjunta juego obtendrá la materia relacionada adjunta también. Puede haber un patrón más limpio pero mi pensamiento es para separar las plataformas del juego, coloque el juego con el contexto, lo marca como añadido. Entonces me gustaría unir las plataformas con el contexto. Serán "sin cambios". A continuación, añadir a la colección games.platform. Las plataformas seguirán sin cambios, pero el . se entenderá

Es posible que haya intentado eso. Tendría que hacerlo yo mismo y ver el estado de entidad de todo sobre la marcha para ver a ciencia cierta lo que está pasando. La clave es que EF tiene que realizar un seguimiento de que a relación se ha añadido y que hay de nuevo (y resultará en una fila en la tabla de unión que se añade), pero entender que las plataformas no son nuevos.

hth Julie

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top