使用EntityFramework 6和Linq批量更新对象列表

问题描述 投票:0回答:3

我想创建一个函数,该函数接受已经设置了属性的对象列表,并且仅对数据库进行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();
        }
    }
c# linq entity-framework linq-to-sql
3个回答
2
投票

删除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();
    }
}

1
投票

没有必要为每个产品调用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/。我听说过,但从未使用过]


0
投票

这与其他方法有点不同。...

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;
}

上面提到的代码片段执行了一些其他任务,以提高性能,并且我们可以指定每个批处理中需要包含的记录数

如果要插入批量记录,则为每个批次创建新的上下文并在任务完成后处置。大大提高了性能(从分钟到操作到秒)

© www.soinside.com 2019 - 2024. All rights reserved.