EF Core 2.2.3을 사용하여 .Net Core 2.2.0에서 엔티티를 업데이트하는 데 문제가 있습니다.
변경 사항을 저장하는 중에 오류가 발생했습니다. 오류 세부 사항 : { 'Id'}에 대해 동일한 키 값을 가진 다른 인스턴스가 이미 추적 중이므로 엔티티 유형 'Asset'의 인스턴스를 추적 할 수 없습니다. 기존 엔터티를 연결할 때는 지정된 키 값을 가진 엔터티 인스턴스가 하나만 연결되어 있는지 확인하십시오. 사용을 고려하십시오
DB 컨텍스트를 등록하는 방법은 다음과 같습니다.
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
가 Scoped
경우
... "이 경우 각 요청마다 서비스의 새 인스턴스가 작성됩니다"
PUT 요청의 컨텍스트가 GET 요청의 컨텍스트와 다른 경우 엔티티는 이미 어떻게 추적되고 있습니까? 가장 기본적인 수준에서 어떻게 작동합니까?
그것이 작동되도록하는 유일한 방법은 모든 항목의 상태를 설정하는 것입니다 ChangeTracker
에 EntityState.Detached
. 그렇다면 그것은 효과가 있습니다. 그러나 적어도 내 현재의 지식에는 말이되지 않습니다.
이 질문을 찾았지만 EF가 추적을 수행하는 방법에 대한 해결 방법과 가정만으로는 올바른 대답이 없습니다.
업데이트 다음은이 문제를 재현하는 샘플이 포함 된 비트 버킷에 대한 링크입니다. EF Core Update Sample
컨텍스트에서 검색된 객체를 직렬화했습니다.
기본적으로 엔티티를 검색 할 때 엔티티를 추적하고 추적하기 때문에 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;
}
}