c# - EF : The instance of entity type X cannot be tracked because another instance of this type with the same key is already being tracked

标签 c# asp.net-mvc asp.net-core entity-framework-core

我在我的 http 请求中发送一个 Json 格式的用户实体,如下所示:

POST http://localhost:52054/api/Authentication/DeleteAccessToken HTTP/1.1
Host: localhost:52054
Content-Type: application/json

{"id":1,"userName":"mnoureldin","accessToken":{"id":1,"token":"123ABC456EFG","userId":1}}

我的 Controller (在 EF-core 中)是这样处理的:

[HttpPost]
public IActionResult DeleteAccessToken([FromBody]User user)
{
    using (var Context = new UnitOfWork().Context)
    {
        var userEntity = Context.Users.Find(user.Id); // Get the real entity of the user received as json
        if (userEntity != null)
        {
            var accessTokenEntity = Context.AccessTokens.Find(userEntity.AccessToken.Id); // Find the entity of the accesstoken (I tried also directly by accessing the navigation property of user entity)
            Context.AccessTokens.Remove(accessTokenEntity);
            return Ok();
        }
        else
        {
            return Unauthorized();
        }
    }
}

但是行 Context.AccessTokens.Remove(accessTokenEntity); 抛出这个异常:

An exception of type 'System.InvalidOperationException' occurred in Microsoft.EntityFrameworkCore.dll but was not handled in user code

Additional information: The instance of entity type 'AccessToken' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.

我也尝试过直接从 userEntity 访问 AccessToken 导航属性,但出现相同的异常。

这是我的 UnitOfWork 初始化:

public UnitOfWork()
{
    // Configure EF connection
    var optionsBuilder = new DbContextOptionsBuilder<CustomDbContext>();
    optionsBuilder
        .UseMySQL(@"server=192.168.1.35; port=3306; sslmode=none;
                    userid=root;
                    pwd=P@ssword;
                    database=dotnet;");

    Context = new CustomDbContext(optionsBuilder.Options);

    // Configure data loading method to explicit
    Context.AccessTokens.Load();
}

我的 CustomBdContext:

public class CustomDbContext : DbContext
{
    // Tell EF to map the entities to tables
    public DbSet<User> Users { get; set; }
    public DbSet<AccessToken> AccessTokens { get; set; }

    public CustomDbContext(DbContextOptions options) : base(options)
    {
    }
}

我有以下具有一对一关系的简单数据模型:

User ----- AccessToken

用户:

public class User
{
    public int Id { get; set; }
    public string UserName { get; set; }

    public virtual AccessToken AccessToken { get; set; }
}

访问 token :

public class AccessToken
{
    public int Id { get; set; }
    public string Token { get; set; }

    [ForeignKey("User"), Required]
    public int UserId { get; set; }
    public virtual User User { get; set; }
}

有人可以帮我解决这个问题吗?我不明白到底发生了什么..

最佳答案

似乎 EF 已经在跟踪 user 和其中的 AccessToken。因此,让我们尽量避免获取同一实体的另一个实例并重用已跟踪的实例。

尝试

[HttpPost]
public IActionResult DeleteAccessToken([FromBody]User user)
{
    // Requires System.Linq
    if (Context.Users.Any(u => u.Id == user.Id))
    {
        var accessTokenEntity = Context.AccessTokens.Find(user.AccessToken.Id); // Find the entity of the accesstoken (I tried also directly by accessing the navigation property of user entity)
        Context.AccessTokens.Remove(accessTokenEntity);

        // NOTE: You re not saving?
        return Ok();
    }
    else
    {
        return Unauthorized();
    }
}

或者尝试:

[HttpPost]
public IActionResult DeleteAccessToken([FromBody]User user)
{
    if (Context.Users.Any(u => u.Id == user.Id))
    {
        Context.AccessTokens.Remove(user.AccessToken);
        return Ok();
    }
    else
    {
        return Unauthorized();
    }
}

关于c# - EF : The instance of entity type X cannot be tracked because another instance of this type with the same key is already being tracked,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42607030/

相关文章:

asp.net-mvc - 为 dnx rc2 运行 MVC 6 ASP.NET 5 本地化示例

asp.net-core - 在容器的核心控制台应用程序中获取ASPNETCORE_ENVIRONMENT

c# - 在 Web Api 中找到与请求匹配的多个操作

c# - 无法引用项目对其运行单元测试

c# - 如何打开带附件的默认电子邮件客户端

C# 如何捕获泛型抽象类构造函数的异常

c# - 是否可以在不中断调试的情况下在 Visual Studio 中查看执行函数列表?

asp.net-core - ASP.NET MVC6 脚手架在 BETA 8 中不起作用

c# - Asp.net 按钮点击事件和 MVC

asp.net - 替代 asp.net MVC View 引擎