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
Why Is It Considered Bad to Expose List<T>
Enable Options Header for Cors on .Net Core Web API
How to Add an Event to a Usercontrol in C#
Get the Active Color of Windows 8 Automatic Color Theme
Xmlwriter to Write to a String Instead of to a File
Waiting for Async/Await Inside a Task
How to Hide "Chrome Is Being Controlled by Automated Software" Infobar Within Chrome V76
Limiting Double to 3 Decimal Places
Multi-Select Dropdown List in ASP.NET
Md5 Hash with Salt for Keeping Password in Db in C#
In Mvvmcross How to Do Custom Bind Properties