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);
}
}
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();
}
}
}
I'm stumped.