如何防止Automapper替换Entity Framework拥有的实体?

时间:2018-01-13 01:51:52

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

我有两种类型。位置和位置有一个地址。地址使用

指定为owned entity
class LocationConfiguration : IEntityTypeConfiguration<Location>
{
    public void Configure(EntityTypeBuilder<Location> builder)
    {
        builder.HasKey(location => new { location.SubscriptionId, location.Id });
        builder.OwnsOne(location => location.Address);
    }
}

我正在获取现有的Location实体并使用Automapper映射更新的值。

[HttpPut("{subscriptionId}/{locationId}")]
public async Task<IActionResult> SaveLocationAsync(string subscriptionId, long locationId, [FromBody] Location location)
{
    if (location == null || location.Id != locationId || location.SubscriptionId != subscriptionId)
    {
        return BadRequest();
    }
    var dbLocation = await locations.GetLocationAsync(subscriptionId, locationId);
    if (dbLocation == null)
    {
        return NotFound();
    }
    mapper.Map<Location, Location>(location, dbLocation);
    return Ok(await locations.SaveAsync(dbLocation));
}

我通过致电context.SaveChangesAsync();

来保存

但我收到了错误

  

InvalidOperationException:实体类型的实例   &#39; Location.Address#地址&#39;无法跟踪,因为另一个实例   使用键值&#39; LocationSubscriptionId:123,LocationId:1&#39;是   已被跟踪。更换自有实体时修改   不更改实例的属性或分离以前拥有的属性   实体入口优先。

我怀疑Automapper正在替换Location的Address属性,而不是导航并单独替换Address的属性。

是否有办法让Automapper更精细地复制属性值?

1 个答案:

答案 0 :(得分:4)

您应该使用UseDestinationValue

在所有者类型映射配置中配置此类属性
  

UseDestinationValue告诉AutoMapper不要为某个成员创建新对象,而是使用目标对象的现有属性。

此外,如果您在示例中使用自映射,请确保为每个拥有的类型创建显式自映射。

对于您的示例,所需行为的最小AutoMapper配置如下:

cfg.CreateMap<Address, Address>();

cfg.CreateMap<Location, Location>()
    .ForMember(dest => dest.Address, opt => opt.UseDestinationValue());