简体   繁体   English

即使使用 AsNoTracking 也无法跟踪实体类型的实例

[英]The instance of entity type cannot be tracked even with AsNoTracking

I receive an error in test environment, but not on the prod environment even as no tracking has already been placed.我在测试环境中收到错误,但在 prod 环境中没有收到错误,即使尚未放置跟踪。

Error "GetUserAsync: System.InvalidOperationException: The instance of entity type 'UserEntity' cannot be tracked because another instance with the key value '{Id: 1}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.错误“GetUserAsync:System.InvalidOperationException:无法跟踪实体类型“UserEntity”的实例,因为已在跟踪另一个具有键值“{Id:1}”的实例。附加现有实体时,请确保只有一个实体实例具有附加了给定的键值。

Code:代码:

internal async Task<UserEntity> GetUserAsync(CancellationToken cancellationToken)
{
    var result = await _userDataQuery.GetLatestUser(cancellationToken);
}

I already added AsNoTracking :我已经添加了AsNoTracking

public async Task<UserEntity> GetLatestUser(CancellationToken cancellationToken)
{
    var result = await this.Entities
                           .OrderByDescending(m => m.Id)
                           .AsNoTracking().FirstOrDefaultAsync();
    await Context.Entry(result).ReloadAsync();

    return result;
}

Not sure if this help but the I also notice the pg_sequences on postgreSQL between the two environments are different for User Table and both of them only have 1 record in the table不确定这是否有帮助,但我也注意到两个环境之间 postgreSQL 上的 pg_sequences 对于用户表是不同的,并且它们在表中只有 1 条记录

Test Environment:测试环境:

last_value = 2

Prod Environment:产品环境:

last_value = 1

This error means that within the lifetime scope of the DbContext (Context) that entity has already been loaded and is being tracked.此错误意味着在DbContext (上下文)的生命周期 scope 内,该实体已经被加载并正在被跟踪。 This could be directly via a different method call, or indirectly by being eager or lazy loaded as part of another entity load.这可以直接通过不同的方法调用,或者间接通过作为另一个实体加载的一部分被急切或延迟加载。 Reload will attempt to track the entity which will result in an error where another matching instance is already tracked. Reload将尝试跟踪实体,这将导致另一个匹配实例已被跟踪的错误。

From what I can make of what you are trying to do, you probably don't want to use AsNoTracking() since you cannot guarantee that the entity hasn't already been tracked.根据我对您正在尝试做的事情的了解,您可能不想使用AsNoTracking()因为您不能保证该实体尚未被跟踪。 Load it as-per normal.照常加载。

var result = await this.Entities
                       .OrderByDescending(m => m.Id)
                       .FirstAsync();
await Context.Entry(result).ReloadAsync();

Whenever you use an *OrDefault() flavour, you must handle the fact that there may be no items in the set.每当您使用*OrDefault()风格时,您必须处理集合中可能没有项目的事实。 If you expect at least one, use First .如果您期望至少有一个,请使用First

The downside here is that Reload will be called even when the desired item is already freshly loaded from the DB.这里的缺点是即使已经从数据库中新加载了所需的项目,也会调用 Reload。 Since we cannot assume the desired item is or isn't already tracked, about the best option would probably be:由于我们不能假设所需的项目已被跟踪或尚未被跟踪,因此最佳选择可能是:

var id = this.Entities
             .OrderByDescending(m => m.Id)
             .Select(x => x.Id)
             .FirstAsync();

var result = this.Entities.Local
                       .Where(m => m.Id == id)
                       .SingleOrDefault();
if (result != null)
    await Context.Entry(result).ReloadAsync();
else
    result = this.Entities
        .Where(m => m.Id == id)
        .Single();

This code looks for a particular item in the local tracking cache, if found it will reload it, otherwise it will load the current item from the DB.此代码在本地跟踪缓存中查找特定项目,如果找到它将重新加载它,否则它将从数据库中加载当前项目。

This approach (minus selecting the ID from the DB) would apply in any other situations where you know ahead of time what specific entity you want rather than relying on something like FirstOrDefault and want to ensure any already tracked entity is available and refresh it.这种方法(减去从数据库中选择 ID)将适用于您提前知道所需的特定实体而不是依赖于FirstOrDefault类的东西并希望确保任何已跟踪的实体可用并刷新它的任何其他情况。

Just check below things.只需检查以下内容。

  1. whether you're doing context.Update( or context.Entity.Update( anywhere in the code. (this might cause such issues)无论您是在代码中的任何位置执行context.Update(还是context.Entity.Update( 。(这可能会导致此类问题)
  2. Make sure to not hold the DbContext instance for too long.确保不要持有 DbContext 实例太久。 By MS recommendation they should be either Transient or Scoped (and not singleton).根据 MS 的建议,它们应该是 Transient 或 Scoped(而不是单例)。

If you're doing context.Update( anywhere in the code and holding the DbContext instance for considerably long time, there will be high chances you're trying to update the same tracked entity multiple times in the DbContext lifetime.如果您在代码中的任何地方执行context.Update(并长时间持有 DbContext 实例,那么您很有可能在 DbContext 生命周期内多次尝试更新同一个跟踪实体。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 "使用 AsNoTracking() 获取“无法跟踪实体类型的实例,因为已经在跟踪具有相同键值的另一个实例”" - Getting 'The instance of entity type cannot be tracked because another instance with same key value for is already being tracked' with AsNoTracking() 无法跟踪实体类型的实例 - The instance of entity type cannot be tracked 实体类型“”的实例无法跟踪 - The instance of entity type '' cannot be tracked 实体类型的实体框架实例无法跟踪 - Entity Framework instance of entity type cannot be tracked InvalidOperationException:无法跟踪实体类型&#39;ApplicationUser&#39;的实例 - InvalidOperationException: The instance of entity type 'ApplicationUser' cannot be tracked 实体类型Menu的实例无法追踪 - The instance of entity type Menu cannot be tracked HostedService:无法跟踪实体类型的实例 - HostedService: The instance of entity type cannot be tracked 无法跟踪实体类型“BookLoan”的实例 - The instance of entity type 'BookLoan' cannot be tracked InvalidOperationException:无法跟踪实体类型“Vessels”&gt; 的实例,因为另一个实例 - InvalidOperationException: The instance of entity type 'Vessels' > cannot be tracked because another instance 实体框架核心 - 无法跟踪实体类型的实例,因为已在跟踪具有键值的另一个实例 - Entity framework Core - The instance of entity type cannot be tracked because another instance with the key value is already being tracked
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM