【发布时间】: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