2015-04-16 108 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; 
     } 
    } 
} 
相關問題