How to Bulk Update Records in Entity Framework

How to Bulk Update records in Entity Framework?

If you don't want to use an SQL statement, you can use the Attach method in order to update an entity without having to load it first :

using (myDbEntities db = new myDbEntities())
{
try
{
//disable detection of changes to improve performance
db.Configuration.AutoDetectChangesEnabled = false;

//for all the entities to update...
MyObjectEntity entityToUpdate = new MyObjectEntity() {Id=123, Quantity=100};
db.MyObjectEntity.Attach(entityToUpdate);

//then perform the update
db.SaveChanges();
}
finally
{
//re-enable detection of changes
db.Configuration.AutoDetectChangesEnabled = true;
}
}

C# Entity Framework: Bulk Update with Where and Join

If EF Extensions is out, what about EFCore.BulkExtensions?

await _dbContext.Set<Product>()
.Where(x => x.Manufacturer == "ABC Company" &&
x.StartYear == 2019 &&
x.ProductType.ProductTypeDescription == "Electronics")
.BatchUpdateAsync(x => new Product(){
Manufacturer = "XYZ Company",
StartYear = 2020 });

Note update is performed as raw sql, objects loaded into the change tracker are not updated. You may wish to surround the bulk operations and SaveChangesAsync in a transaction.

YMMV, I haven't used this library myself.

C# Entity Framework Bulk Update

I would suggest changing the following:

    Domain.Tables.Inventory _inventory = db.Inventories
.Where(x => x.InventoryID == inventory.InventoryID)
.FirstOrDefault();

To

Domain.Tables.Inventory _inventory = db.Inventories
.Single(x => x.InventoryID == inventory.InventoryID);

I'd still add the db.Configuration.AutoDetectChangesEnabled = false; after getting the context, and also use AsNoTracking:
Turn off EF change tracking for any instance of the context

Entity Framework 6 Where in Bulk Update/Delete in one transaction

Unfortunately, this is not supported in Entity Framework out of the box. However, you can use the batch update functionality in the EntityFramework.Extended library:

https://github.com/loresoft/EntityFramework.Extended

There's a nuget package available, too.

An example would be:

using EntityFramework.Extensions;

...

int[] myIds = { 592, 593, 594 };

using (var context = _dataContextFactory.GetContext())
{
// Define a filter expression to retrieve matching items
var filter = context.MyTables.Where(item => myIds.Contains(item.Id));
// Update the StatusId of matched items
context.MyTables.Update(filter, i => new Item { StatusId = 3 });

// NB: no context.SaveChanges() required
}

NB: there may be a more efficient way of writing this, but I'm still playing with the library. It does compile down to a single SQL statement, however, and the library also includes batched DELETEs.

Finally, don't worry about the new expression. Any properties which are not referenced here will retain their original values.

Entity Framework Core bulk update underlying collections

I would suggest linq2db.EntityFrameworkCore (disclaimer: I'm one of the creators)

Then you can do the following:

var updateQuery =
from a in ctx.Assembly
join s in ctx.Station on a.SationId equals s.ID
join p in ctx.Project on s.ProjectId equals p.ID
where p.ID == projectId
select a;

var recordsAffected = await updateQuery
.Set(a => a.OnHold, onHold)
.Set(a => a.UpdatedWith, updatedWith)
.Set(a => a.UpdatedAt, a => Sql.CurrentTimeStamp)
.Set(a => a.UpdatedById, updatedById)
.UpdateAsync();

If you have defined appropriate navigation properties, query can be simplified and joins can be removed.

var recordAffected = await ctx.Assembly
.Where(a => a.Station.ProjectId == projectId)
.Set(a => a.OnHold, onHold)
.Set(a => a.UpdatedWith, updatedWith)
.Set(a => a.UpdatedAt, a => Sql.CurrentTimeStamp)
.Set(a => a.UpdatedById, updatedById)
.UpdateAsync();


Related Topics



Leave a reply



Submit