首页 > 解决方案 > EF Core:更新数千条记录失败

问题描述

我正在使用 EF Core 更新名为 MyTable 的表中的数千条记录。它已经有 1.500.000 行。这是我用来更新其属性之一的简单代码 MyProp 为每条记录使用不同的值:

using (MyDbContext ctx = new MyDbContext())
{
      var rows = ctx.Set<MyTable>().Take(1000000).ToList(); // I only take the first 1 million rows
      int idx = 0;
      foreach (var row in rows)
      {
           row.MyProp = $"MyNewValue{idx++}";
      }
      ctx.SaveChanges();
}

如果我用一百万行来更新它们,在调用 ctx.SaveChanges() 时,我会得到以下异常:Expected to read 4 header bytes but only received 0.(参见下面的完整堆栈跟踪)

我不知道为什么我会遇到这样的异常,如果我取 1000000 行,但如果我只取 750000 则不会。我读到它可能与 SQL 服务器的超时有关:下面列出,但我真的不知道它是否真的与一个超时有关以及如何找到解决方案。我应该将更新分成几个并调用几次 SaveChanges() 吗?

感谢您的任何建议。

以下是来自 MySql 服务器的超时:

连接超时 10

延迟插入超时 300

have_statement_timeout 是

innodb_flush_log_at_timeout 1

innodb_lock_wait_timeout 50

innodb_print_lock_wait_timeout_info 关闭

innodb_rollback_on_timeout 关闭

交互超时 610

lock_wait_timeout 31536000

net_read_timeout 30

net_write_timeout 60

rpl_stop_slave_timeout 31536000

slave_net_timeout 60

线程池空闲超时 60

等待超时 610

这是完整的堆栈跟踪: 来自 Microsoft.EntityFrameworkCore.Update:错误保存上下文类型“MyDbContext”的更改时数据库中发生异常。Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> MySql.Data.MySqlClient.MySqlException (0x80004005): 读取结果集失败。---> System.IO.EndOfStreamException:预期读取 4 个标头字节,但仅收到 0。在 MySqlConnector.Protocol.Serialization.ProtocolUtility.DoReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func1 getNextSequenceNumber, ArraySegmentHolder1 previousPayloads, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\Protocol\Serialization\ProtocolUtility.cs:第 462 行在 MySqlConnector.Protocol.Serialization.StandardPayloadHandler.ReadPayloadAsync(ArraySegmentHolder`1 缓存, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\Protocol\Serialization\StandardPayloadHandler.cs:第 37 行,在 C:\projects\mysqlconnector\src\ 中的 MySqlConnector.Core.ServerSession.ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancelToken) MySqlConnector\Core\ServerSession.cs:第 665 行

标签: exceptionentity-framework-core

解决方案


对于您的用例,因为您想设置一个显式值,您可以执行一些不会在服务器上返回任何行的直接 sql。

阅读这个精彩的章节,您实际上可以将整个操作转换为仅在 db 上运行的简单 sql 语句。分页(跳过)部分将被移动到数据库中,不会检索任何数据以节省性能并且整个操作不会消耗服务器上的内存


推荐阅读