作者:X巩工916BGR_426 | 来源:互联网 | 2022-12-06 18:44
我是EF的新手,正在努力进行似乎基本的更新。我已经阅读了许多有关类似问题的文章。据我所知,目前在EF Core 2.1中不容易做到这一点,并且需要一个复杂的解决方法。这实际上可行吗?还是我应该直接直接且单独地更新子实体?
注意:如果我只是更新exampleA而不包含子实体,则可以正常工作。
我收到以下错误:
处理请求时发生未处理的异常。InvalidOperationException:无法跟踪实体类型“ ExampleB”的实例,因为已经跟踪了另一个具有相同“ {'Id”}键值的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'来查看冲突的键值。Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap.ThrowIdentityConflict(InternalEntityEntry条目)
堆栈查询COOKIE标头InvalidOperationException:无法跟踪实体类型ExampleB的实例,因为已经跟踪了另一个具有相同键值的{'Id'}的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'来查看冲突的键值。
我创建了该问题的基本示例。第一个stackoverflow帖子也让我知道是否需要更多信息。
任何帮助将不胜感激。
WebAPI控制器:
[HttpPut]
public async Task UpdateExample(ExampleADto exampleADto)
{
var exampleAFromDB = await _context.ExampleA.Include(x => x.ExampleBs).Where(x => x.Id == exampleADto.Id).SingleOrDefaultAsync();
if (exampleAFromDB == null)
return NotFound();
_mapper.Map(exampleADto, exampleAFromDB);
if (await _context.SaveChangesAsync() > 0)
return Ok(exampleAFromDB);
throw new Exception("Failed to update ExampleA");
}
更新之前在数据库中的exampleA:
{
"id": 1,
"description": "Example A1",
"exampleBDtos": [
{
"id": 1,
"description": "B1",
"someNumber": 1
},
{
"id": 2,
"description": "B2",
"someNumber": 2
},
{
"id": 3,
"description": "B3",
"someNumber": 3
}
]
}
exampleADto:
{
"id": 1,
"description": "Example A1 Updated",
"exampleBDtos": [
{
"id": 1,
"description": "B1 Updated",
"someNumber": 1
},
{
"id": 2,
"description": "B2",
"someNumber": 2
},
{
"id": 3,
"description": "B3",
"someNumber": 3
}
]
}
自动映射后的exampleA:
{
"id": 1,
"description": "Example A1 Updated",
"exampleBDtos": [
{
"id": 1,
"description": "B1 Updated",
"someNumber": 1
},
{
"id": 2,
"description": "B2",
"someNumber": 2
},
{
"id": 3,
"description": "B3",
"someNumber": 3
}
]
}
更新失败后数据库中的exampleA(无更改):
{
"id": 1,
"description": "Example A1",
"exampleBDtos": [
{
"id": 1,
"description": "B1",
"someNumber": 1
},
{
"id": 2,
"description": "B2",
"someNumber": 2
},
{
"id": 3,
"description": "B3",
"someNumber": 3
}
]
}
AutoMapper配置文件:
public AutoMapperProfiles()
{
CreateMap()
.ForMember(x => x.ExampleBDtos, opt => opt.MapFrom(x => x.ExampleBs));
CreateMap();
CreateMap()
.ForMember(x => x.ExampleBs, opt => opt.MapFrom(x => x.ExampleBDtos));
CreateMap();
}
更新1:
自动映射后添加对象
更新2:
似乎Automapper不会在不删除并重新创建与EF混淆的项目的情况下映射集合。
AutoMapper.Collection https://www.nuget.org/packages/AutoMapper.Collection/当前不适用于EF Core,因此我自己创建了一个函数来手动映射和更新集合。