Home > OS >  EF Core update an existing entity
EF Core update an existing entity

Time:05-24

I'm using EF Core and .NET 6 and I would like to essentially upsert an entity to a table - a fairly simple ask.

I have the following code:

var countries = GetCountries();

using (var scope = scopeFactory.CreateScope())
{
    var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

    foreach (var c in countries)
    {
        // check if the country already exists.
        var exists = dbContext.Countries.Where(d => d.Id == c.Id).FirstOrDefault();

        // if already exists - update (rather than add).
        if (exists != null) 
        {
            exists.Name = c.Name;
            exists.DisplayName = c.DisplayName;
            ... // omitted other prop updates.

            dbContext.Countries.Update(exists);
        } 
        else
        {
            dbContext.Countries.Add(c);
        }
    }

    await dbContext.SaveChangesAsync();
}

I was wondering - is there was a more efficient way to update without manually looking up then updating (it's not very performant).

Preferably, I was hoping there was a Merge method in EF Core but can't find anything useful (that's free...). Rather than doing the manual lookup and update in this way.

I'm probably missing something very obvious here - thanks for any pointers in advance!

CodePudding user response:

EF Core do not have Merge, or similar for Upsert. You can improve performance of your query by selecting existng items in one batch. Also you do not need to call Update, just change properties.

var countries = GetCountries();

using (var scope = scopeFactory.CreateScope())
{
    var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

    var countyIds = countries.Select(c => c.Id);
    var existing = (await dbContext.Countries.Where(d => countyIds.Contains(d.Id))
        .ToListAsync())
        .ToDictionary(c => c.Id);

    foreach (var c in countries)
    {
        // check if the country already exists.

        if (existing.TryGetValue(c.Id, out var toUpdate))
        {
            // if already exists - update (rather than add).
            toUpdate.Name = c.Name;
            toUpdate.DisplayName = c.DisplayName;
            ... // omitted other prop updates.
        } 
        else
        {
            dbContext.Countries.Add(c);
        }
    }

    await dbContext.SaveChangesAsync();
}

CodePudding user response:

public void InsertOrUpdate(Entity entity) 
{ 
    using (var context = new dbContext.Countries()) 
    { 
        context.Entry(entity).State = entity.Id == 0 ? 
                                   EntityState.Added : 
                                   EntityState.Modified; 

        context.SaveChanges(); 
    } 
}
  • Related