【问题标题】:Using automapper to update entities with relationships使用自动映射器更新具有关系的实体
【发布时间】:2017-04-28 15:58:50
【问题描述】:

我正在使用 EF Core 和 Automapper 来更新我的实体。我有一个名为“Aluno”的实体,它与“Endereco”有关系。代码如下:

public class Aluno : ApplicationUser{

    ...
    public Endereco Endereco { get; set; }
    ...
}

public class AlunoViewModel : UserViewModel
{
    public int Id { get; set; }

    public EnderecoViewModel Endereco { get; set; }
}

public class Endereco{

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get;set; }

   ...
}

public class EnderecoViewModel {

    public int Id { get;set; }
    ...
}

自动映射器配置:

config.CreateMap<Aluno, AlunoViewModel>().ReverseMap();
config.CreateMap<Endereco, EnderecoViewModel>().ReverseMap();

AlunosController:

[HttpPut]
    public JsonResult Put([FromBody]AlunoViewModel vm)
    {
        if (ModelState.IsValid)
        {
            var aluno = _context.Alunos
                .Single(o => o.Id == vm.Id);

            Mapper.Map(vm, aluno);

            _context.SaveChanges();

            Response.StatusCode = (int)System.Net.HttpStatusCode.OK;
            return Json(true);
        }

        Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
        return Json(false);
    }

当我尝试更新“Aluno”实体时,我在 context.SaveChanges() 上遇到异常:

无法为表“Enderecos”中的标识列插入显式值 当 IDENTITY_INSERT 设置为 OFF 时。

但我并没有尝试插入新的“Endereco”,只是更新实体“Aluno”,并且可能更新“Endereco”,它在 var aluno 中正确加载。

我做错了吗?

【问题讨论】:

  • 我认为你有映射问题。请在保存操作之前检查您的映射是否正确。您的 Aluno 映射需要“ForMember”函数来定义其属性对象的映射。您可以尝试添加 ForMember(i => i.Endereco, i => i.MapFrom(s =>s.Endereco))。
  • 你是对的!您可以将其发布为答案,以便我标记它吗?谢谢!
  • @Munir:请不要滥用 AutoMapper 绑定回实体,这会给您带来很大的麻烦,尤其是在映射回集合时。 AutoMapper 是并且从未打算用于两种方式的映射。请在此处阅读 AutoMapper 作者的帖子lostechies.com/jimmybogard/2009/09/18/…,了解 AutoMapper 适用于哪些用例并且可以正常工作。尝试将其滥用于两种方式绑定会导致 a)您的域模型破坏封装以支持该方式,以及 b)您的持久性模型/ORM 映射器存在绑定问题。
  • 查看这篇博文以了解为什么将 AutoMapper 与 ORM(ViewModel 到持久性模型绑定)一起使用是不好的和邪恶的,并且会导致您在编写代码时做噩梦rogerjohansson.blog/2013/12/01/… 如果您使用它可能会很好其他方式(Persistence Model -> dto 或 viewmodel,但也可能通过触发同步发生的延迟加载给您带来麻烦,因此阻止您的 ASP.NET 请求线程返回到线程池)
  • @Tseng,我同意你的看法。我解决了上面的问题,但我现在遇到了很多与 Automapper 相关的其他问题。在进行插入或更新时,我决定将属性直接从 ViewModel 映射到实体。感谢您的参考,非常有帮助。

标签: c# asp.net-core automapper entity-framework-core


【解决方案1】:

试试下面的语法:

Mapper
    .CreateMap<Aluno, AlunoViewModel>()
    .ForMember(
        dest => dest.Endereco,
        opt => opt.MapFrom(src => src.EnderecoViewModel)
    );

【讨论】:

  • 对不起,需要投票。虽然它可以解决眼前的问题,但您只是在鼓励 OP 和其他人以错误的方式使用 AutoMapper。 AutoMapper 不打算以两种方式绑定到域模型或持久性模型! lostechies.com/jimmybogard/2009/09/18/…
  • 我不鼓励任何人使用任何特定的方式做任何事情,只是展示了如果他们使用 AutoMapper 应该如何使用它,无需对@Tseng 投反对票
  • @Tseng,虽然您的观点几乎是正确的,但我认为否决答案是不公平的。它解决了问题,并且投票不会帮助其他人。真正有用的是用您认为最合适的解决方案发布答案​​。
猜你喜欢
  • 2020-06-01
  • 1970-01-01
  • 2022-08-14
  • 2018-04-29
  • 2018-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-27
相关资源
最近更新 更多