实体框架核心中的批量更新

Adr*_*and 3 .net c# entity-framework entity-framework-core

我从数据库中提取了一堆时间表条目,并使用它们来创建发票.保存发票并拥有ID后,我想用发票ID更新时间表条目.有没有办法批量更新实体而不是一次加载一个实体?

void SaveInvoice(Invoice invoice, int[] timeEntryIds) {
    context.Invoices.Add(invoice);
    context.SaveChanges();

    // Is there anything like?
    context.TimeEntries
        .Where(te => timeEntryIds.Contains(te.Id))
        .Update(te => te.InvoiceId = invoice.Id);
}
Run Code Online (Sandbox Code Playgroud)

Lib*_*tad 17

从 EFCore 7.0 开始,您将看到内置函数BulkUpdate()BulkDelete方法:

   context.Customers.Where(...).ExecuteDelete();
   context.Customers.Where(...).ExecuteUpdate(c => new Customer { Age = c.Age + 1 });
   context.Customers.Where(...).ExecuteUpdate(c => new { Age = c.Age + 1 });
   context.Customers.Where(...).ExecuteUpdate(c => c.SetProperty(b => b.Age, b => b.Age + 1));
Run Code Online (Sandbox Code Playgroud)

  • 给发现此内容的任何人注意 - EFCore 7 尚未发布,预计将于 2022 年 11 月发布。 (4认同)

Jon*_*nan 10

免责声明:我是项目Entity Framework Plus的所有者

我们的库有一个批量更新功能,我相信你正在寻找

此功能支持EF Core

// Is there anything like? YES!!!
context.TimeEntries
    .Where(te => timeEntryIds.Contains(te.Id))
    .Update(te => new TimeEntry() { InvoiceId = invoice.Id });
Run Code Online (Sandbox Code Playgroud)

维基:EF批量更新


Des*_*Fox 6

如果TimeEntryInvoice(检查导航属性)有关联,您可能可以执行以下操作:

var timeEntries = context.TimeEntries.Where(t => timeEntryIds.Contains(te.Id)).ToArray();

foreach(var timeEntry in timeEntries)
    invoice.TimeEntries.Add(timeEntry);

context.Invoices.Add(invoice);

//save the entire context and takes care of the ids
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)


Dha*_*777 5

您追求简化语法的性能吗?

我建议使用直接 SQL 查询,

 string query = "Update TimeEntries Set InvoiceId = <invoiceId> Where Id in (comma separated ids)";    
 context.Database.ExecuteSqlCommandAsync(query);
Run Code Online (Sandbox Code Playgroud)

对于逗号分隔的 id,你可以这样做 string.Join(',', timeEntryIds)

这取决于您实际需要什么。如果你想使用 Linq,那么你需要遍历每个对象。