2015-04-16 68 views
0

我正试图加密一些数据,其中我的表有五十万条记录。 Fastest Way of Inserting in Entity Framework - - 这里的答案启发我试图块我的更新通过调用递归函数:EntityFramework中发生未处理的异常类型'System.StackOverflowException'

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); 
     } 
    } 

我开始了与1270 maxRetry值,但当它下降到360,我就行了StackOverflow的异常:每次更新后

var phones = context.Phones... 

鉴于我处置背景和重新创建500条记录,我不确定为什么我得到这个异常。

+3

此异常不是EF造成的。它是由你的递归函数调用自己太深造成的。而不是递归使用循环。 – usr

+0

downvoter会关心告诉我应该如何提出更好的问题? –

回答

0

的调用堆栈中的EncryptFields的过度重复运行的深度看起来是这样的(其中,例如,它的第一个电话是在深度10):

10, 11, 12, ... 

调用的深度您的EF查询,则是这个样子:

11, 12, 13, ... 

假设你能去为N.最大深度然后当你到EncryptFields呼叫在深度N,它会尝试调用EF查询在深度N + 1。这就是为什么你得到StackOverflowException内部的EF查询,而不是直接在您的递归方法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; 
     } 
    } 
} 
相关问题