DbContext.Attach在Ef Core 3.0和2.2上的行为不同,失败并显示“无法跟踪实体类型的实例”

我正在将使用EF Core 2.2的ASP.NET Core 2.2应用程序迁移到ASP.NET Core 3.0和EF Core 3.0。

在一种特定的方法上,后端从前端接收DTO,并使用Automapper将其转换为等效的实体类型,并将其附加到DbContext,然后保存。 这在EF Core 2.2上可以完美运行,但在EF Core 3.0上失败,并显示以下消息:

The instance of entity type 'ServiceProvider' cannot be tracked because another
instance with the same key value for {'Id'} is already being tracked

这是有问题的代码:

var sqresponse = _mapper.Map<SurveyQuestionResponse>(sqresponseDTO);

_context.Attach(sqresponse); // <=== Throws exception
_context.SaveChanges();

这是具有相关类别的实体:

public class SurveyQuestionResponse
{
    public int? Id { get; set; }
    public List<Answer> Answers { get; set; } = new List<Answer>();
}

public class Answer
{
    public int? Id { get; set; }
    public int SurveyQuestionResponseId { get; set; }
    public ServiceProvider ServiceProvider { get; set; }
}

从前端传递到该方法的数据有两个Answer,它们都包含一个ServiceProviderId = 56

{
    answers: [
        {
            // some more properties here
            serviceProviderId: 56,serviceProvider: { id: 56,name: "Foo" },},{
            // some more properties here
            serviceProviderId: 56,}
    ]
}

这两个ServiceProvider实体是存在于数据库中的;在这种情况下,我需要将两个Answer与具有ServiceProvider的现有{Id: 56}实体相关联 对于EntityFramework Core 3.0来说,这似乎是一个问题,但是对于EF Core 2.2来说,这是完全可以的。

我怀疑这与this breaking change: DetectChanges honors store-generated key values有关,但是我认为拟议的缓解措施将解决此特定问题,但在尝试插入新的ServiceProvider实体时会创建另一个问题。我说得对吗?

如何使其与EF Core 3.0配合使用?

hangzhoushuangyu 回答:DbContext.Attach在Ef Core 3.0和2.2上的行为不同,失败并显示“无法跟踪实体类型的实例”

这在EFCore 2.2中也不起作用,因此您的用法/测试用例必须足够不同。

提交的JSON将反序列化到您的实体对象中。相关属性serviceProvider将反序列化/具体化每个答案实体对象的实体对象-这意味着,在您的示例中,两个答案对象将引用两个不同的ServiceProvider对象,它们具有相同的ID 。附加了其引用的answer对象时,EFCore还将尝试附加其引用的ServiceProvider对象,但是尝试附加第二个答案对象将抛出您收到的错误,因为上下文已经在跟踪{{ 1}}具有相同ID且不是同一对象的实体。

您需要先检查是否已跟踪该实体,然后再尝试将其添加到上下文中,这意味着您不能盲目地将DTO附加到上下文中。

在通过ServiceProvider连接answer对象之前,首先检查是否存在该类型的实体对象,其上下文已经跟踪到相同的ID,并将该对象分配给{{1} }属性:

DTO
,

我最后通过确保仅填充answer.ServiceProviderId且在连接时answer.ServiceProvidernull来解决了这个问题。

现在传递给后端的JSON如下所示:

{
    answers: [
        {
            // some more properties here
            serviceProviderId: 56,serviceProvider: null,},{
            // some more properties here
            serviceProviderId: 56,}
    ]
}

这样,对_context.Attach(...)_context.SaveChanges()的调用就可以正常工作。

本文链接:https://www.f2er.com/3116023.html

大家都在问