【发布时间】:2016-12-05 19:34:12
【问题描述】:
型号:
public class Client{
public int Id {get;set;}
public string Name {get;set;}
public Address Address {get;set;}
public int AddressId {get;set;}
}
public class Address{
public int Id
public string Address1 {get;set;}
public string PostCode {get;set;}
}
查看模型:
public class ClientViewNodel{
public int Id {get;set;}
public string Name {get;set;}
public Address Address {get;set;}
public int AddressId {get;set;}
}
public class AddressViewModel{
public int Id
public string Address1 {get;set;}
public string PostCode {get;set;}
}
映射:
Mapper.Initialize(config =>
{
config.CreateMap<ClientViewModel, Client>().ReverseMap();
config.CreateMap<AddressViewModel, Address>().ReverseMap();
});
控制器更新操作:
[HttpPost]
public async Task<IActionResult> Update(cLIENTViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View("Client",viewModel);
}
var client= _clientRepository.GetClient(viewModel.Id);
if (client == null)
return NotFound();
client= Mapper.Map<ClientViewModel, Client>(viewModel);
_clientRepository.Update(client);
var result = await _clientRepository.SaveChangesAsync();
if (result.Success)
{
return RedirectToAction("Index");
}
ModelState.AddModelError("", result.Message);
return View("Client",viewModel);
}
问题是当_clientRepository.Update(client) 被调用时,我收到一条错误消息:
无法跟踪实体类型“客户端”的实例,因为已在跟踪具有相同键的该类型的另一个实例。添加新实体时,对于大多数键类型,如果未设置键(即,如果键属性为其类型分配了默认值),则会创建一个唯一的临时键值。如果您为新实体显式设置键值,请确保它们不会与现有实体或为其他新实体生成的临时值发生冲突。附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文。
当我调试代码时,我可以看到,当我将 viewModel 映射到模型时,客户端模型中的 AddressID 设置为 0。我猜这是导致问题的原因。
如何将 viewModel 映射回模型,其中地址的详细信息将被更新,例如 Address1 和 Postcode 而不是 Id。
我还尝试在 .ForMember(x => x.AddressId, opt => opt.Ignore()) 的映射中忽略 Id for Address 的映射
但它仍然将 AddressId 设置为 0。
我错过了什么?
【问题讨论】:
-
抱歉直接说,但您使用 AutoMapper 的方式完全错误! AutoMapper从来没有用于双向映射,它的作者 Jimmy Bogard 从来没有一个合理的用例。当你仔细观察它时,除了懒惰之外,没有理由进行 2 路映射。随时阅读 Jimmy 的这篇 lostechies.com/jimmybogard/2009/09/18/… 的帖子,他解释了为什么以及它的用例。它总是从域或持久性模型到 dto 或 ViewModel!
-
因此,当您从 MVC 操作或 WebAPI 调用中获得回传时,只需像使用 AutoMapper 之前一样执行此操作。使用 ID,从数据库中获取模型,更新它的字段,调用 SaveChanges()(或者不调用,如果发生了一些事情并且你想回滚它)。无论如何,您都需要验证您的数据,并且根据您的逻辑,某些字段在某些条件下不会结转(即,如果订单未包装为“包装为礼物”,则不要将“用户问候”添加到订单中
-
这也可能对你有用:devtrends.co.uk/blog/…
-
当我看复数视觉教程时,他们都用它来做 2 路映射。我可以看到这样做的危险。但他们也说一个动作必须最多 10 行。那么告诉我如何在不使用自动映射器的情况下将动作保持 10 行?当我需要将 10 多个属性映射回模型时?我应该将视图模型传回服务并在服务中进行映射?
-
首先它是一个指导方针,而不是硬性规则。如果他们在这些教程中使用 AutoMapper 和 2 向绑定,他们也不了解该工具。你会质疑工具的作者和 DDD 的专家吗? :P 其次,我认为这些人将代码行与指令混淆了。当您将每个属性分配放在新行中时,它仍然是一个“指令”,只是分成多行。您可能还想阅读这个rogerjohansson.blog/2013/12/01/… 关于该主题的内容通过这次尝试让自己远离恐怖
标签: c# asp.net-core asp.net-core-mvc automapper-5