gpt4 book ai didi

c# - EF 核心 'another instance is already being tracked'

转载 作者:太空狗 更新时间:2023-10-29 21:52:43 25 4
gpt4 key购买 nike

我在使用 EF Core 2.2.3 更新 .Net Core 2.2.0 中的实体时遇到问题。

An error occurred while saving changes. Error details: The instance of entity type 'Asset' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using

这是注册数据库上下文的方式:

services.AddDbContext(选项=>

options.UseSqlServer(Configuration.GetConnectionString("DbConnection")), ServiceLifetime.Scoped);

Scoped 生命周期是默认设置的,但我写它是为了更容易理解。

Anomaly 对象是这样得到的:

public IQueryable<Anomaly> GetAll()
{return _context.Anomalies.Include(a => a.Asset).Include(a => a.Level)
}

public async Task<Anomaly> GetAnomaly(int anomalyId, User user)
{
var anomaly = await GetAll()
.FirstOrDefaultAsync(a => a.Id == anomalyId);

return anomaly;
}

Update() 方法如下所示:

using (var transaction = _context.Database.BeginTransaction())
{
try
{
_context.Anomalies.Update(anomaly);
_context.SaveChanges();

transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw;
}
}

它包含此交易之前的一些检查,但在此上下文中没有足够的相关性。

这就是我遇到错误的地方,实例已经被跟踪。我不明白这是怎么发生的。如果上下文是 Scoped,那么

... "a new instance of the service will be created for each scope", in this case, for each request

如果我在 PUT 请求上的上下文与 GET 请求的上下文不同,那么实体是如何被跟踪的?这在最基本的层面上是如何运作的?

让它工作的唯一方法是将所有条目的状态从 ChangeTracker 设置为 EntityState.Detached。然后它就起作用了..但它没有任何意义,至少就我目前的知识而言..

我找到了 this question但没有有效的答案,只有关于 EF 如何进行跟踪的变通办法和假设。


UPDATE Here is a link to bitbucket with a sample recreating this problem: EF Core Update Sample

我序列化了从上下文中检索到的对象。

在左侧有跟踪 <====> 在右侧没有跟踪 With Tracking on the LEFT <====> With NO tracking on the RIGHT

最佳答案

默认情况下,当您检索实体时,它们会被跟踪,并且由于它们被跟踪,您可以只调用 SaveChanges 而不是调用 Update。您还可以使用 .AsNoTracking()

检索实体而不跟踪它们

如果尚未跟踪,则需要调用 Update,因此如果您使用 AsNoTracking,则需要在 SaveChanges 之前使用 Update

public IQueryable<Anomaly> GetAll()
{ return _context.Anomalies
.Include(a => a.Asset)
.Include(a => a.Level);
}

public async Task<Anomaly> GetAnomaly(int anomalyId, User user)
{
var anomaly = await GetAll()
.AsNoTracking()
.FirstOrDefaultAsync(a => a.Id == anomalyId);

return anomaly;
}

您还可以检查实体是否被跟踪以了解是否调用更新:

using (var transaction = _context.Database.BeginTransaction())
{
try
{

bool tracking = _context.ChangeTracker.Entries<Anomaly>().Any(x => x.Entity.Id == anomaly.Id);
if (!tracking)
{
_context.Anomalies.Update(anomaly);
}

_context.SaveChanges();

transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw;
}
}

关于c# - EF 核心 'another instance is already being tracked',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56240764/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com