使用 EntityFramework 6 和 Linq 批量更新对象列表
Batch update on object list using EntityFramework 6 and Linq
我想创建一个函数,该函数接受已设置属性的对象列表,并对其进行批量更新或插入,仅对数据库进行 1 次调用。
(更新)这是工作版本:
public static void BatchInsertProducts(IList<Product> productList)
{
using (var context = new DbContext())
{
context.Products.AddRange(productList);
context.SaveChanges();
}
}
这是我尝试根据 ID 更新或插入多个项目。我不认为我可以在这里使用 AddRange 所以我这样试了但我收到一个错误:
public static void SaveMultipleProducts(IList<Product> productList)
{
using (var context = new DbContext())
{
foreach (Account p in productList)
{
if (p.ID == 0)
{
context.Entry(p).State = EntityState.Added;
p.InsertUserId = "jtunney";
p.InsertDate = DateTime.Now;
}
else
{
context.Entry(p).State = EntityState.Modified;
p.UpdateUserId = "jtunney";
p.UpdateDate = DateTime.Now;
}
}
context.SaveChanges();
}
}
不必为每个产品调用保存方法。如果您获取产品并使用相同的 DbContext 保存,您只需调用一次保存,然后它将保存您的所有修改。
想象一下
List<Product> products = Context.Product.ToList();
foreach(var product in products)
{
product.Price = new Random().Next();
}
Context.Product.SaveChanges();
此代码正在修改列表中所有产品的价格,但由于我们使用相同的上下文来检索结果,并且 EF implements Tracking 通过一次调用 SaveChanges 来保存修改够了
对于批量插入
使用 Entity Framework http://www.entityframeworktutorial.net/EntityFramework6/addrange-removerange.aspx or you can try this library https://efbulkinsert.codeplex.com/ 中的 AddRange 方法。听说过,没用过
删除了 foreach 循环,将 IList<Product>
更改为 IEnumerable<Product>
:
public static void BatchInsertProducts(IEnumerable<Product> productList)
{
using (var context = new DbContext())
{
context.Products.AddRange(productList);
context.SaveChanges();
}
}
保存多个的一种方法:
public static void SaveMultipleProducts(IEnumerable<Product> productList)
{
using (var context = new DbContext())
{
foreach (Account p in productList)
{
p.InsertUserId="jtunney";
p.InsertDate=DateTime.Now;
context.Entry(p).State=p.Id==0?EntityState.Added:EntityState.Modified;
}
context.SaveChanges();
}
}
另一种方式:
public static void SaveMultipleProducts(IList<Product> productList)
{
using (var context = new DbContext())
{
foreach (Account p in productList)
{
p.InsertUserId="jtunney";
p.InsertDate=DateTime.Now;
}
// Add all records
context.Products.AddRange(productList);
// Handle updates
foreach(var p in productList.Where(p=>p.id!=0))
{
context.Entry(p).State=EntityState.Modified;
}
context.SaveChanges();
}
}
This is bit different approach than other....
public static DbContext BatchInsertProducts(DbContext context,IList<Product> productList)
{
context.Configuration.AutoDetectChangesEnabled = false;
for (int i = 0; i < lobbies.Count; i += 100)
{
context.Set<Product>().AddRange(lobbies.GetRange(i, Math.Min(100, lobbies.Count - i)));
context.Products.AddRange(productList);
context.SaveChanges();
//Dispose and create a context
context.Dispose();
context = new DbContext;
context.Configuration.AutoDetectChangesEnabled = false;
}
return context;
}
上面提到的代码片段做了一些额外的任务以提高性能,我们也可以指定需要的记录数包含在每个批次操作中。
If we want to insert bulk records, creating new context for each batch
and dispose then once task is done. very much improve the performance
(from minutes to operation to seconds)
我想创建一个函数,该函数接受已设置属性的对象列表,并对其进行批量更新或插入,仅对数据库进行 1 次调用。
(更新)这是工作版本:
public static void BatchInsertProducts(IList<Product> productList)
{
using (var context = new DbContext())
{
context.Products.AddRange(productList);
context.SaveChanges();
}
}
这是我尝试根据 ID 更新或插入多个项目。我不认为我可以在这里使用 AddRange 所以我这样试了但我收到一个错误:
public static void SaveMultipleProducts(IList<Product> productList)
{
using (var context = new DbContext())
{
foreach (Account p in productList)
{
if (p.ID == 0)
{
context.Entry(p).State = EntityState.Added;
p.InsertUserId = "jtunney";
p.InsertDate = DateTime.Now;
}
else
{
context.Entry(p).State = EntityState.Modified;
p.UpdateUserId = "jtunney";
p.UpdateDate = DateTime.Now;
}
}
context.SaveChanges();
}
}
不必为每个产品调用保存方法。如果您获取产品并使用相同的 DbContext 保存,您只需调用一次保存,然后它将保存您的所有修改。
想象一下
List<Product> products = Context.Product.ToList();
foreach(var product in products)
{
product.Price = new Random().Next();
}
Context.Product.SaveChanges();
此代码正在修改列表中所有产品的价格,但由于我们使用相同的上下文来检索结果,并且 EF implements Tracking 通过一次调用 SaveChanges 来保存修改够了
对于批量插入
使用 Entity Framework http://www.entityframeworktutorial.net/EntityFramework6/addrange-removerange.aspx or you can try this library https://efbulkinsert.codeplex.com/ 中的 AddRange 方法。听说过,没用过
删除了 foreach 循环,将 IList<Product>
更改为 IEnumerable<Product>
:
public static void BatchInsertProducts(IEnumerable<Product> productList)
{
using (var context = new DbContext())
{
context.Products.AddRange(productList);
context.SaveChanges();
}
}
保存多个的一种方法:
public static void SaveMultipleProducts(IEnumerable<Product> productList)
{
using (var context = new DbContext())
{
foreach (Account p in productList)
{
p.InsertUserId="jtunney";
p.InsertDate=DateTime.Now;
context.Entry(p).State=p.Id==0?EntityState.Added:EntityState.Modified;
}
context.SaveChanges();
}
}
另一种方式:
public static void SaveMultipleProducts(IList<Product> productList)
{
using (var context = new DbContext())
{
foreach (Account p in productList)
{
p.InsertUserId="jtunney";
p.InsertDate=DateTime.Now;
}
// Add all records
context.Products.AddRange(productList);
// Handle updates
foreach(var p in productList.Where(p=>p.id!=0))
{
context.Entry(p).State=EntityState.Modified;
}
context.SaveChanges();
}
}
This is bit different approach than other....
public static DbContext BatchInsertProducts(DbContext context,IList<Product> productList)
{
context.Configuration.AutoDetectChangesEnabled = false;
for (int i = 0; i < lobbies.Count; i += 100)
{
context.Set<Product>().AddRange(lobbies.GetRange(i, Math.Min(100, lobbies.Count - i)));
context.Products.AddRange(productList);
context.SaveChanges();
//Dispose and create a context
context.Dispose();
context = new DbContext;
context.Configuration.AutoDetectChangesEnabled = false;
}
return context;
}
上面提到的代码片段做了一些额外的任务以提高性能,我们也可以指定需要的记录数包含在每个批次操作中。
If we want to insert bulk records, creating new context for each batch and dispose then once task is done. very much improve the performance (from minutes to operation to seconds)