我正在尝试加密一些数据,其中我的表有五十万条记录。灵感来自这里的答案 - Fastest Way of Inserting in Entity Framework - 我试图通过调用递归函数来更新我的更新:
IDBContext context;
try{
context = new MyDbContext();
context.Configuration.AutoDetectChangesEnabled = false;
EncryptFields(context, 500, (count / 500));
}
finally{
if (context != null)
{
context.Dispose();
}
}
这里的递归函数:
private static void EncryptFields(IDBContext context, int batchSize, int maxRetries)
{
Debug.WriteLine(maxRetries.ToString());
if (maxRetries == 0)
{
return;
}
var phones = context.Phones
.Where(p => !(p.Number == null
|| p.Number.Trim() == String.Empty))
.Take(batchSize)
.ToList();
if (phones.Count() > 0)
{
foreach (var phone in phones)
{
phone.Enc_Number = Encrypt(phone.Number);
}
context.SaveChanges();
context.Dispose();
context = new MyDBContext();
context.Configuration.AutoDetectChangesEnabled = false;
EncryptFields(context, batchSize, --maxRetries);
}
}
我开始时的maxRetry
值为1270,但是当它降到360时,我得到了一个StackOverflow异常:
var phones = context.Phones...
鉴于我处理了上下文并在更新每500条记录后重新创建它,我不确定为什么会收到此异常。
答案 0 :(得分:0)
重复运行时堆栈中EncryptFields
的调用深度看起来像这样(例如,第一次调用它的深度为10):
10, 11, 12, ...
对EF查询的调用深度如下所示:
11, 12, 13, ...
假设您可以访问的最大深度为N.然后,当您对EncryptFields
的呼叫位于深度N时,它将尝试在深度N + 1处调用EF查询。这是为什么要在EF查询中获取StackOverflowException
而不是直接在递归方法EncryptFields
中。
这不是EF问题;异常恰好在那里表现出来,因为您的EF查询深入了解了EncryptFields
方法。解决这个问题的方法就是消除递归。
private static void EncryptFields(IDBContext context, int batchSize, int maxRetries)
{
while (true)
{
Debug.WriteLine(maxRetries.ToString());
if (maxRetries == 0)
{
return;
}
var phones = context.Phones
.Where(p => !(p.Number == null || p.Number.Trim() == ""))
.Take(batchSize)
.ToList();
if (phones.Count() > 0)
{
foreach (var phone in phones)
{
phone.Enc_Number = Encrypt(phone.Number);
}
context.SaveChanges();
context.Dispose();
context = new MyDBContext();
context.Configuration.AutoDetectChangesEnabled = false;
maxRetries--;
continue;
}
else
{
break;
}
}
}