Search code examples
entity-framework-coreasp.net-core-webapi.net-7.0

Entity Framework updating database discreetly


I have a project where I save weather data to a database as my caching mechanism.

  • ASP.NET Core 7 Web API
  • Deployed to Azure web app
  • Azure Postgres DB

When a request comes in I check the database to see if I have data for that location less than 30 minutes old. I do this to avoid expensive API calls. I save the data in metric, so I convert it when an imperial request comes along. I am having an issue where this converted value gets saved back into the database, so when the next request comes around and converts, it's effectively converting the same data 2 times. I cannot figure out where or how this converted data gets saved to the database. My question is, can Entity Framework save or update the database without explicitly being asked to do so? I write logs in my Repository class where I CRUD the database.

public async Task<WeatherForecast> CreateWeatherForecast(WeatherForecast weatherForecast)
{
    dbContext.WeatherForecasts.Add(weatherForecast);
    await dbContext.SaveChangesAsync();
    logger.LogInformation("(Repo)CreateWeatherForecast: {Id}, {Temp}", id, weatherForecast.Daily[0].Temp.Max);
    return weatherForecast;
}

public async Task<WeatherForecast?> GetWeatherForecastById(int id)
{
    var weatherForecast = await dbContext.WeatherForecasts.FindAsync(id);

    if (weatherForecast != null)
        logger.LogInformation("(Repo)GetWeatherForecastById: {Id}, {Temp}", id, weatherForecast.Daily[0].Temp.Max);

    return weatherForecast;
}

And these are the logs I get:

8152: (Repo)CreateWeatherForecast: 239, 287.76
8153: got forecast: 239, from "ExternalRefreshed" temps: 287.76
8154: Converted temp: 58.3
// a while later... 
8412: (Repo)GetWeatherForecastById: 239, 58.3

As you can see, the next read after the write returns the converted temps, but nowhere in between was there ever a write logged. So that almost 100% means Entity Framework is writing to the database without being instructed to!


Solution

  • looks like you are facing this problem because of await dbContext.SaveChangesAsync();, it will save all changes made in this context to the underlying database.

    To avoid happening this issue you could use:

    1)context.Entry(yourObject).State = EntityState.Detached

    2)Reset the entity's state to Unchanged dbContext.Entry(weatherForecast).State = EntityState.Unchanged;

    3)Use var weatherForecast = await dbContext.WeatherForecasts.AsNoTracking().FirstOrDefaultAsync(f => f.Id == id);

    You can refer this similar post which can give more option: How do I stop Entity Framework from trying to save/insert child objects?