开发者

EF4 not updating many-to-many graph; Or, is there a better way to handle many-to-many in EF4?

开发者 https://www.devze.com 2023-03-14 23:46 出处:网络
My current problem seems like a mutant version of what I ran into a few months ago (see: Problems updating w/ EF4 repo & MVC2 - can't update many-to-many graph).I can create a new Game-Platfor

My current problem seems like a mutant version of what I ran into a few months ago (see: Problems updating w/ EF4 repo & MVC2 - can't update many-to-many graph). I can create a new Game-Platform graph, but I can't edit the Platform side of an existing graph. So, I can't add/remove Platforms from the relationship.

I'm using AutoMapper to map the incoming data to entities. I'm then manually attaching the Game entity to the ObjectContext in my repository, and manually setting its EntityState based on whether I'm creating a new entity graph, or updating an existing one. Here's my current setup:

AutoMapper mapping:

Mapper.CreateMap<AdminGameEditModel, Game>()
    .BeforeMap((s, d) =>
    {
        foreach (var platId in s.PlatformIDs)
        {
            Platform newPlat = _gameRepository.GetPlatform(platId);

            d.Platforms.Add(newPlat);
        }
    })
    .ForMember(dest => dest.BoxArtPath, opt => opt.Ignore())
    .ForMember(dest => dest.IndexImagePath, opt => opt.Ignore())
    .ForMember(dest => dest.Cons, opt => opt.MapFrom(src => String.Join("|", src.Cons)))
    .ForMember(dest => dest.Pros, opt => opt.MapFrom(src => String.Join("|", src.Pros)))
    .ForMember(dest => dest.LastModified, opt => opt.UseValue(DateTime.Now))
    .ForMember(dest => dest.Platforms, opt => opt.Ignore());

The GetPlatform method of my repo:

public Platform GetPlatform(int id)
{
    Platform plat = _siteDB.Platforms.FirstOrDefault(pl => pl.PlatformID == id);
    _siteDB.Detach(plat);

    return plat;
}

And my SaveGame method:

public void SaveGame(Game game)
{
    _siteDB.Games.Attach(game);

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

    _siteDB.SaveChanges();
}

My only thought is that I need to Remove() the Platforms of the existing G开发者_运维知识库ame entity. I'm not sure how to do that gracefully with my current setup as I already have an incoming fresh Game entity being sent to SaveGame() that has the new list of Platforms. I feel like there has to be a better, more graceful way of doing things.

So, any ideas? I'm trying to keep references to my UI (view/edit models and the like) from creeping into my domain layer, so I don't want my repo to deal with my AdminGameEditModel directly.


There is no way to do it gracefully. What you have to do is:

  • Get your view model as is (a new state)
  • Load the Game from the database together with all its platforms (current persisted state)
  • Write a code which will go through the new state and add or modify platforms in the current state
  • Write a code which will go through the current state and remove all platforms not included in the new state
  • Save changes

Simply once you post new state from the view where you removed some platforms you lost the information about them and you must first load the current state from database to find which platforms you must delete.

Another more brutal approach is loading current state, clearing platform collection (all relations are removed) and then add all platforms from the new state.

0

精彩评论

暂无评论...
验证码 换一张
取 消