如何防止 Automapper 替换实体框架拥有的实体?

Ric*_*tte 1 c# automapper entity-framework-core .net-core asp.net-core-webapi

我有两种类型。位置和位置有一个地址。地址被指定为拥有的实体,使用

class LocationConfiguration : IEntityTypeConfiguration<Location>
{
    public void Configure(EntityTypeBuilder<Location> builder)
    {
        builder.HasKey(location => new { location.SubscriptionId, location.Id });
        builder.OwnsOne(location => location.Address);
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在获取现有的 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));
}
Run Code Online (Sandbox Code Playgroud)

我通过打电话来节省 context.SaveChangesAsync();

但我收到错误

InvalidOperationException:无法跟踪实体类型“Location.Address#Address”的实例,因为已跟踪具有键值“LocationSubscriptionId:123, LocationId:1”的另一个实例。替换拥有的实体时,修改属性而不更改实例或首先分离先前拥有的实体条目。

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

有没有办法让 Automapper 对属性值进行更精细的复制?

Iva*_*oev 6

您应该在所有者类型映射配置中配置此类属性UseDestinationValue

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

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

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

cfg.CreateMap<Address, Address>();

cfg.CreateMap<Location, Location>()
    .ForMember(dest => dest.Address, opt => opt.UseDestinationValue());
Run Code Online (Sandbox Code Playgroud)