I am working on an ASP.NET Core application using Entity Framework Core for data access. I am encountering an issue when trying to edit a FiscalYear entity in my database. I have the following code:
public async Task<Response> EditFiscalYear(FiscalYear fiscalYear)
{
try
{
var validate = await EditFiscalYearValidate(new FiscalYearValidationModel { Object = fiscalYear });
if (validate.StatusCode == System.Net.HttpStatusCode.BadRequest)
return validate;
_context.EditEntity(fiscalYear);
await _context.SaveChangesAsync();
return SuccessResponse(resultObject: fiscalYear, resultText: "Fiscal Year Updated Successfully");
}
catch (Exception ex)
{
return FaultResponse(ex.Message);
}
}
And the validation method is:
public async Task<Response> EditFiscalYearValidate(FiscalYearValidationModel model)
{
if ((await _context.PayPeriods
.AnyAsync(x => x.FiscalYearId == model.Object.FiscalYearId)))
{
return FaultResponse("Fiscal Year Dependency found");
}
var fiscalYear = await _context.FiscalYears.FirstOrDefaultAsync(x => x.FiscalYearId == model.Object.FiscalYearId);
if (fiscalYear is null)
return NotFoundResponse("No Fiscal Year Found");
// Other validation checks...
return SuccessResponse();
}
Here is the EditEntity function for more clarity:
public void EditEntity<TEntity>(TEntity entity, List<string> excludedParams = null)
{
var entry = this.Entry(entity);
entry.State = EntityState.Modified;
//some other modifications
}
When I try to edit a FiscalYear entity, I get the following exception:
"The instance of entity type 'FiscalYear' cannot be tracked because another instance with the same key value for {'FiscalYearId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values."
I understand that EF Core is complaining because it's trying to track two instances of the same entity at the same time. However, I'm puzzled because when I don't store the result of FirstOrDefaultAsync in a variable, I don't get the exception:
await _context.FiscalYears.FirstOrDefaultAsync(x => x.FiscalYearId == model.Object.FiscalYearId);
Why does this happen?
As a solution I am currently doing
var fiscalYear = _context.FiscalYears.AsNoTracking().FirstOrDefaultAsync(x => x.FiscalYearId == model.Object.FiscalYearId);
This solves my problem but I still don't understand why the tracking behaviour doesn't manifest in the same manner for
await _context.FiscalYears.FirstOrDefaultAsync(x => x.FiscalYearId == model.Object.FiscalYearId);