使用MVC和修改后的嵌套实体的自动映射 - 如何更新它们

时间:2015-03-07 12:58:04

标签: asp.net-mvc entity-framework asp.net-mvc-5 automapper

我正在使用automapper将我的实体映射到一个viewmodel,并从视图中将viewmodel形成回旅程中的实体。

我遇到了一个小问题,我在修改后的对象中有一个嵌套实体列表,可以在视图中修改。当我保存主对象时,即使一切似乎在其嵌套实体中正确映射,嵌套实体也不会更新(在控制台中看不到与它们相关的SQL语句)。

我很确定我会怀疑确保EF知道他们已经被修改过了。

我发现的唯一一件事就是通知框架我的控制器中的实体已被修改(即使不是全部):

Database.Entry(character).State = EntityState.Modified;
foreach(CharacterAbilityScore cab in character.CharacterAbilityScores)
    Database.Entry(cab).State = EntityState.Modified;

如果我没记错的话,当我在视图中使用实体而不是ViewModels时,我不需要通知EF嵌套实体被修改,它知道并相应地更新了数据库。

我只是想确保我有正确的方法。

告诉我你是否需要更多代码!

更新

这是我配置automapper的方式:

Mapper.CreateMap<CharacterViewModel, Character>()
    .ForMember(dest => dest.CharacterAbilityScores, opt => opt.MapFrom(src => src.CharacterAbilityScoresDTO));

最终更新,回答:

由于我处于MVC模式,并且当我们从视图上的帖子返回时重新创建上下文,我必须手动管理我的子实体如何更改,无论是使用自我跟踪实体还是像我一样,标记当我知道他们可能会修改它们时。它会导致更多的更新,而不是必要的。

2 个答案:

答案 0 :(得分:2)

您需要独立于主要实体映射您的收藏。否则,AutoMapper将使用映射的类替换整个集合,而不是将新值实际映射到现有项。

在您的配置中,告诉AutoMapper在映射时忽略您的集合:

AutoMapper.Mapper.CreateMap<CharacterViewModel, Character>()
    .ForMember(dest => dest.CharacterAbilityScores, opts => opts.Ignore());

然后,在您的操作中分两步映射发布的数据:

AutoMapper.Mapper.Map(model, character);
foreach (var item in model.CharacterAbilityScores)
{
    var existingItem = character.CharacterAbilityScores.SingleOrDefault(m => m.Id == item.Id);
    if (existingItem == null)
    {
        character.CharacterAbilityScores.Add(AutoMapper.Mapper.Map<CharacterAbilityScore>(item));
    }
    else
    {
        AutoMapper.Mapper.Map(item, existingItem);
    }
}

答案 1 :(得分:0)

由于我处于MVC模式,并且当我从视图上的帖子返回时重新创建了上下文,Entity Framework只能跟踪父对象,而不是嵌套的父对象。

因此,我必须手动管理我的子实体的更改方式,无论是使用自我跟踪实体还是像我一样,在我知道它们可能的时候标记它们。它会导致更多的更新,而不是必要的。

因此,要么使用自我跟踪实体(请参阅此博文)http://blog.tonysneed.com/2013/11/18/trackable-entities-versus-self-tracking-entities/,要么将其标记为&#34;已修改&#34;就像我在原始问题中做的那样(导致更多的更新,如果仍然很少,可以接受)。