我想创建一个函数,该函数接受已经设置了属性的对象列表,并且仅对数据库进行1次调用就进行批量更新或插入。
(UPDATE)这是工作版本:
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();
}
}
删除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();
}
}
没有必要为每个产品调用Save方法。如果您获得产品并使用相同的DbContext保存,则只需调用一次Save,它将保存所有修改。
想象
List<Product> products = Context.Product.ToList();
foreach(var product in products)
{
product.Price = new Random().Next();
}
Context.Product.SaveChanges();
此代码正在修改列表中所有产品的价格,但是由于以下事实:我们使用相同的上下文来检索结果,并且只需单击一次SaveChanges就可以使用EF implements Tracking保存修改,就足够了。
对于bulkInserts
使用实体框架http://www.entityframeworktutorial.net/EntityFramework6/addrange-removerange.aspx中的AddRange方法,也可以尝试使用此库https://efbulkinsert.codeplex.com/。我听说过,但从未使用过]
这与其他方法有点不同。...
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;
}
上面提到的代码片段执行了一些其他任务,以提高性能,并且我们可以指定每个批处理中需要包含的记录数。
如果要插入批量记录,则为每个批次创建新的上下文并在任务完成后处置。大大提高了性能(从分钟到操作到秒)