无法使用Entity Framework Core 2.1更新子实体

时间:2018-08-23 22:23:49

标签: entity-framework-core automapper-5

我是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<ActionResult> 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
        }
    ]
}

自动映射后的示例A:

{
"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<ExampleA, ExampleADto>()
            .ForMember(x => x.ExampleBDtos, opt => opt.MapFrom(x => x.ExampleBs));
        CreateMap<ExampleB, ExampleBDto>();

        CreateMap<ExampleADto, ExampleA>()
            .ForMember(x => x.ExampleBs, opt => opt.MapFrom(x => x.ExampleBDtos));
        CreateMap<ExampleBDto, ExampleB>();
    }

更新1: 自动映射后添加对象

更新2: 似乎Automapper不会在不删除并重新创建与EF混淆的项目的情况下映射集合。

AutoMapper.Collection https://www.nuget.org/packages/AutoMapper.Collection/当前不适用于EF Core,因此我自己创建了一个函数来手动映射和更新集合。

0 个答案:

没有答案