【问题标题】:Alternative to bulk update with Entity Framework [duplicate]使用实体框架进行批量更新的替代方法 [重复]
【发布时间】:2015-06-22 00:50:12
【问题描述】:

我有一个包含 100,000 多条记录的表。客户要求我们加密用户名字段,将加密值复制到新字段,并清除原始用户名字段。加密只能在应用程序中执行,不能在数据库中执行。

现有的代码库过去使用实体框架来完成这些任务,但从来没有用于这种大小的表。旧代码看起来像:

foreach(var phone in db.Phones){
     phone.Enc_Serial = Encrypt(phone.Serial);
     phone.Serial = "";
}
db.SaveChanges();

鉴于这是一次批量更新,使用原始 SQL 命令执行此操作是否有任何优势?我在想至少我们不会有大量的跟踪对象坐在DbContext 消耗内存。

var idsAndSerials = db.Phones.Select(p => new { id = p.Id, serial = p.Serial };
foreach(var item in idsAndSerials ){
    string sql = String.Format("Update phone set Enc_Serial ='{0}' where phoneId={1}", Encrypt(item.serial), item.id.ToString());
    db.Database.ExecuteSqlCommand(sql);
}

【问题讨论】:

  • 出于好奇,这有什么关系?您的旧方法是否无法在足够长的时间内运行?您是否分析过 1k 记录的两种方法之间的区别?
  • 一次更新一次的 foreach 循环需要很长时间。我建议在 C# 端构建表,然后将其插入到数据库上的 Temp 表中,然后运行一次更新。
  • 如果您使用“原始 SQL 命令”执行此操作,那么从技术上讲,您将在数据库中执行加密,而 不是 在应用。 (因为 SQL 命令是由客户端请求,但实际上是由 DBMS 服务器执行)。
  • 除了@SurgeonofDeath 的建议之外,您还可以使用表值参数和存储过程。不会摆脱您在 .NET 端的内存问题,但会摆脱在 SQL 端发生的多个更新。但是我又要问了:你的传统方法真的表现得那么差吗?
  • @DanField 不,旧版功能表现不佳。一位同事担心如此大量的记录在操作过程中会消耗多少内存,所以我想我会把它扔给 SO 上的各位好人以供输入。

标签: c# sql-server entity-framework


【解决方案1】:

由于这是一个重大更新,我建议创建一个跟踪表(在 SQL 端),您可以在其中按顺序编号要更新的每一行(并存储该行的 PK 值)。还包括跟踪表中的一列,可让您将该行标记为已完成(例如 0 或 1)。通过 PK 值在原表中设置外键。

在 EF 端更新您的数据模型以包含新的跟踪表。现在您有了一个新表,可以轻松地让您一次检索 1K 批记录以进行处理。这不会有过多的内存消耗。应用程序逻辑可以进行加密。当您更新这些记录时,请在跟踪表中将更新的记录标记为“完成”。

通过跟踪表获取下 1K 的未完成记录(使用导航属性获取真实记录)。重复。

它会非常快地完成,不会产生过多的负担。 100000+ 条记录并不是很多,特别是如果您使用分而治之的方法(100+ 批)。

【讨论】:

    【解决方案2】:

    在您提供的示例中,不可能。您仍在遍历每条记录并调用UPDATE。至少在第一个示例中,我相信这些语句将作为批处理执行,并且是事务性的,因此所有更新都成功或都不成功。

    【讨论】:

      猜你喜欢
      • 2014-07-12
      • 1970-01-01
      • 1970-01-01
      • 2018-12-03
      • 2012-07-11
      • 1970-01-01
      • 2015-05-10
      • 2022-01-07
      • 2020-12-07
      相关资源
      最近更新 更多