【发布时间】: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