从id列表更新Entity Framework中的多行

all*_*ded 75 c# sql asp.net-mvc entity-framework

我正在尝试为实体框架创建一个查询,这将允许我获取ID列表并更新与它们关联的字段.

SQL中的示例:

UPDATE Friends
SET msgSentBy = '1234'
WHERE id IN (1, 2, 3, 4)
Run Code Online (Sandbox Code Playgroud)

如何将上述转换为实体框架?

Dam*_*ith 136

类似下面的东西

var idList=new int[]{1, 2, 3, 4};
using (var db=new SomeDatabaseContext())
{
    var friends= db.Friends.Where(f=>idList.Contains(f.ID)).ToList();
    friends.ForEach(a=>a.msgSentBy='1234');
    db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

更新:

您可以更新多个字段,如下所示

friends.ForEach(a =>
                      {
                         a.property1 = value1;
                         a.property2 = value2;
                      });
Run Code Online (Sandbox Code Playgroud)

  • 使用此解决方案为列表中的每个元素生成一个更新查询.有没有办法让EF只在问题中做一个查询?(`UPDATE SomeTable SET SomeField = SomeValue WHERE Id IN(...)`) (41认同)
  • 请注意,从数据库的角度来看,这是一种非常低效的方法.这不仅会发出涉及Friends表中每一行的大型select语句,而且会为每个更新的记录发出单独的UPDATE命令.因此,不是发出一个命令,而是发出许多命令以及从数据库中传输大量数据. (15认同)
  • `ForEach`是`List`上的一个方法,一般不鼓励使用它,因为它不是一种非常实用的编程方式.只需使用`foreach`*(操作员)*就像普通人一样. (9认同)
  • 这不应该是公认的答案,它的效率非常低,并且会导致数据库很快耗尽内存, (3认同)
  • @ShekharPankaj,基本上你想要做的是发出一个 SQL 命令,如“UPDATE Friends SET msgSentBy = '1234' WHERE ID IN (1, 2, 3, 4)”。我认为 EF 没有直接支持这样做。我相信有一些第三方解决方案(http://stackoverflow.com/questions/12751258/batch-update-delete-ef5),但我没有使用它们。其他选项是使用原始 ADO.NET 而不是 EF。 (2认同)

San*_*han 18

使用 Entity Framework 7 进行大规模更新的最佳方法如下:

var idList = new int[]{1, 2, 3, 4};
context.Friends
       .Where(f => idList.Contains(f.ID))
       .ExecuteUpdate(f => f.SetProperty(x => x.Name, x => $"Updated {x.Name}"));
Run Code Online (Sandbox Code Playgroud)

这样做的优点是它不会检索所有记录。它只是发送更新查询。

参考:ExecuteUpdate 和 ExecuteDelete(批量更新)


Pet*_*err 11

有两个开源项目允许这样:EntityFramework.Extended和E ntity Framework Extensions.


小智 5

IQueryable.ToQueryString如果您愿意在代码中出现一些原始 SQL,则 Entity Framework Core 5.0 中引入的方法可能会对这种情况有所帮助。此方法将生成可包含在原始 SQL 查询中的 SQL,以对该查询标识的记录执行批量更新。

例如:

using var context = new DbContext();

var ids = new List<int>() { 1, 2, 3, 4 };

var query = context.Friends.Where(_ => ids.Contains(_.id)).Select(_ => _.id);

var sql = $"UPDATE Friends SET msgSentBy = {{0}} WHERE id IN ({query.ToQueryString()})";

context.Database.ExecuteSqlRaw(sql, "1234");
Run Code Online (Sandbox Code Playgroud)

这种方法的主要缺点是使用原始 SQL。但是,我不知道有任何合理的方法可以使用当前的 Entity Framework Core 功能来避免这种情况 - 您会遇到此警告,或此处发布的其他答案的警告,例如:

如果将来解决以下问题,那么我们可能会在这里得到更好的答案:批量(即基于集合的)CUD 操作(无需将数据加载到内存中)#795