AutoMapper 5.2.0 VIewModel 到 Core MVC 中的模型问题
AutoMapper 5.2.0 VIewModel to Model issue in Core MVC
型号:
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)
时,我收到一条错误消息:
The instance of entity type 'Client' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.
当我调试代码时,我发现当我将 viewModel 映射到模型时,客户端模型中的 AddressID 设置为 0。我猜这是导致问题的原因。
如何将 viewModel 映射回将更新地址详细信息(例如 Address1 和邮政编码)而不是 Id 的模型。
我也曾尝试在 .ForMember(x => x.AddressId, opt => opt.Ignore())
的映射中忽略 Id for Address 的映射
但它仍然将 AddressId 设置为 0。
我错过了什么?
当您执行 Mapper.Map<ClientViewModel, Client>(viewModel)
时,AutoMapper 会创建一个新的 Client 对象,其 ID 与现有 Client 对象相同。
然后您指示 EntityFramework 更新此对象图。 Entity Framework 没有跟踪您的新 Client 对象,因此它将该对象附加到其内部魔法 cache/tracking sauce。由于 ID 冲突,此操作失败。因此错误 "The instance of entity type 'Client' cannot be tracked because another instance of this type with the same key is already being tracked".
这也是0
AddressId 的来源。 Address 对象也是一个全新的对象,由 AutoMapper 创建,属性 的值为 default(int)
,因为它在创建后从未被 AutoMapper 分配过另一个值。
型号:
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)
时,我收到一条错误消息:
The instance of entity type 'Client' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.
当我调试代码时,我发现当我将 viewModel 映射到模型时,客户端模型中的 AddressID 设置为 0。我猜这是导致问题的原因。
如何将 viewModel 映射回将更新地址详细信息(例如 Address1 和邮政编码)而不是 Id 的模型。
我也曾尝试在 .ForMember(x => x.AddressId, opt => opt.Ignore())
但它仍然将 AddressId 设置为 0。
我错过了什么?
当您执行 Mapper.Map<ClientViewModel, Client>(viewModel)
时,AutoMapper 会创建一个新的 Client 对象,其 ID 与现有 Client 对象相同。
然后您指示 EntityFramework 更新此对象图。 Entity Framework 没有跟踪您的新 Client 对象,因此它将该对象附加到其内部魔法 cache/tracking sauce。由于 ID 冲突,此操作失败。因此错误 "The instance of entity type 'Client' cannot be tracked because another instance of this type with the same key is already being tracked".
这也是0
AddressId 的来源。 Address 对象也是一个全新的对象,由 AutoMapper 创建,属性 的值为 default(int)
,因为它在创建后从未被 AutoMapper 分配过另一个值。