【问题标题】:Automapper with MVC and modified nested entities - how to update them带有 MVC 和修改的嵌套实体的 Automapper - 如何更新它们
【发布时间】:2015-05-09 00:31:45
【问题描述】:

我正在使用自动映射器将我的实体映射到视图模型,并在从视图返回时将视图模型形成回实体。

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

我很确定我想确保 EF 知道它们已被修改。

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

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

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

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

如果您需要更多代码,请告诉我!

更新:

这是我配置自动映射器的方式:

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

最终更新,答案:

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

【问题讨论】:

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


    【解决方案1】:

    您需要独立于您的主要实体来映射您的集合。否则,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);
        }
    }
    

    【讨论】:

    • 嗯,这不好玩... :) 令我惊讶的是,即使实体中的集合与我的映射配置正确匹配,EF 也无法让它们自行更新,对吗?知道有没有原因?
    • 这是因为 EF 的对象跟踪。通过映射一个全新的集合来代替旧集合,您是在告诉 EF 它应该删除所有这些旧项目,然后添加这些新项目。通过手动将状态设置为已修改,您将导致 EF 附加这些新项目并改为切换到更新模式。
    • 克里斯,当我没有注意到 EF 进行修改时,它没有对集合做任何事情。没有删除和重新创建,没有更新,什么都没有。这就是为什么我有点失落。我还发现我无法自动映射子实体很奇怪(我更新了我的问题以添加我如何为此配置自动映射器)
    • 你的解决方案有问题,由于映射被忽略,集合是空的,所以它为集合中的每个项目创建一个条目,并且 savechanges 失败,因为已经有条目数据库。也许您的意思是我应该与数据库中的内容而不是从 VM 映射的 Character 对象中的内容进行比较?
    【解决方案2】:

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

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

    因此,要么使用自我跟踪实体(请参阅此博客文章)http://blog.tonysneed.com/2013/11/18/trackable-entities-versus-self-tracking-entities/,要么像我在原始问题中所做的那样将它们标记为“已修改”(这会导致比必要的更新更多,如果数量仍然很少,则可以接受)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-06
      • 2021-07-28
      • 2012-07-25
      • 1970-01-01
      • 2017-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多