我有一张包含100,000多条记录的表格。客户已要求我们加密用户名字段,将加密值复制到新字段,并清除原始用户名字段。加密只能在应用程序中执行,而不能在数据库中执行。
现有的代码库过去使用Entity Framework来完成这些任务,但从不使用这种大小的表。遗留代码看起来像:
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);
}
答案 0 :(得分:1)
在您提供的示例中,没办法。您仍在迭代每条记录并致电UPDATE
。至少在第一个例子中,我认为这些语句将作为批处理执行,并且将是事务性的,以便所有更新都成功或者没有一个更新。
答案 1 :(得分:1)
由于这是一次重大更新,我建议创建一个跟踪表(在SQL端),在该表中您按顺序编号要更新的每一行(并且还存储行的PK值) )。还包括跟踪表中的一列,用于将行标记为已完成(例如0或1)。通过PK值将外键设置为原始表。
更新EF端的数据模型以包含新的跟踪表。现在您有了一个新表,可以轻松地检索,例如,1K记录批次一次处理。这不会有过多的内存消耗。应用程序逻辑可以进行加密。在更新这些记录时,请将更新的记录标记为" done"在您的跟踪表中。
通过跟踪表获取下一个未完成记录的1K(使用导航属性获取真实记录)。重复。
它可以非常快速地完成并且没有过度负载。 100000多条记录并不是很多,特别是如果你使用分而治之的方法(100多个批次)。