简体   繁体   中英

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

I am sending a User entity in Json format in my http request like this:

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}}

And my controller (in EF-core ) handles that like this:

[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();
        }
    }
}

But the line Context.AccessTokens.Remove(accessTokenEntity); throws this exception:

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 (ie 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.

I tried also accessing the AccessToken navigation property directly from userEntity with the same exception.

Here is my UnitOfWork initialization:

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();
}

My 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)
    {
    }
}

I have the following simple data model with one to one relationship:

User ----- AccessToken

User:

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

    public virtual AccessToken AccessToken { get; set; }
}

AccessToken:

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; }
}

Could someone help me to solve that? I didn't understand what is exactly happening..

It appears that EF is already tracking user and the AccessToken in it. So, let's try to avoid getting another instance of the same entity and reuse the already tracked one.

Try

[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();
    }
}

Alternatively try:

[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();
    }
}

try replace this line:

var accessTokenEntity = Context.AccessTokens.Find(userEntity.AccessToken.Id);

to:

var accessTokenEntity = Context.AccessTokens.AsNoTracking().Find(userEntity.AccessToken.Id);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

Related Question The instance of entity type 'TestType' cannot be tracked because another instance of this type with the same key is already being tracked The instance of entity type … cannot be tracked because another instance of this type with the same key is already being tracked The instance of entity type 'xTestType' cannot be tracked because another instance of this type with the same key is already being tracked? The instance of entity type 'SalesOrder' cannot be tracked because another instance of this type with the same key is already being tracked The instance of entity type cannot be tracked because another instance of this type with the same key is already being tracked "The instance of entity type 'User' cannot be tracked because another instance with the key value '{x}' is already being tracked with UserManager The instance of entity type 'x' cannot be tracked because another instance with the key value '{Id: 6}' is already being tracked Error: The instance of entity type 'X' cannot be tracked because another instance with the key value '{ID: 3}' is already being tracked The instance of entity type <T> cannot be tracked because another instance with the same key value for {'Id'} is already being tracked The instance of entity type Model cannot be tracked because another instance with the same key value for {'Id'} is already being tracked
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM