2016-10-22 69 views
0

我有一個嵌套列表,並且正在迭代它並將數據插入到我的數據庫中,前提是所有子列表項都已成功插入數據庫。如果在foreach中發生錯誤,請繼續插入

你可以看到我的代碼我使用try catch嵌套迭代,以及爲外迭代和整個代碼被包裹在裏面BeginTransaction.

此代碼工作正常,只要我提供有效的數據。

但是,如果嵌套迭代失敗,原因是一些驗證問題(i.e. SubjectCategoryId not provided)它離開內的foreach做所有迭代後,增加了外層的foreach,嘗試執行SaveChanges但說空的對象引用錯誤失敗。

隨意問我是否需要更多信息。我覺得我錯過了一些小點,尤其是在處理BeginTransaction內嵌的foreach時。

你是否看到我的代碼結構有問題?我使用EF 5

我的代碼:

foreach (var student in Student) 
{ 
    using (var transaction = _context.Database.BeginTransaction()) 
    { 
     try 
     { 
      Student student = new Student 
      { 
       StudentNo = item.Stu_No, 
       Name = item.FullName, 
       Description = item.Description, 
       Phone = item.ContactNo, 
       Address = item.Location 
       Status = item.status 
      }; 

      _context.Student.Add(student); 
      _context.SaveChanges(); // Get Object Null reference error for second iteration if child iteration fails. But works fine if no data issue. 

      var subjectsInfo = student.Subject_Info.GroupBy(pt => new { pt.Subject_Id, pt.SubjectDesc }).ToList(); 
      SubjectInfo subInfo = new SubjectInfo(); 
      SubjectCategory subCat = new SubjectCategory(); 

      foreach(var subjectInfo in subjectsInfo) 
      { 
       try 
       { 
        subInfo.Subject_Id = subjectInfo.Id; 
        subInfo.Description = subjectInfo.Description; 
        subInfo.Id = student.Id; 

        _context.SubjectInfo.Add(subInfo); 
        _context.saveChanges(); 

        subCat.SubjectCategoryId = subjectInfo.SubjectCategoryId; 
        subCat.Status = subjectInfo.Status; 

        _context.SubjectCategory.Add(subCat); 
        _context.saveChanges(); 
       } 
       Catch(Exception ex) 
       { 
         // catch exception 
       } 
      } 
     } 
     Catch(Exception ex) 
     { 
     } 
    } 
} 

我的數據人口:

List<Student> Student= new List<Student>(); 

Student.Add(new Student 
{ 
    BasicInfo = new BasicInfo 
    { 
     Stu_No = "1", 
     FullName = "Steve Adam", 
     ContactNo = "12345", 
     Location = "XYZ", 
     Status = "Active", 
    }, 

    Subject_Info = new List<Subject_Info> 
    { 
     new Subject_Info() { 
     Subject_Id = "1", 
     SubjectDesc = "Math", 

     SubjectCategoryId = "", 
     Status = active 
     }, 

     new Subject_Info() { 
     Subject_Id = "2", 
     SubjectDesc = "Physics", 

     SubjectCategoryId = "", 
     Status = active 
     }, 
    } 
}); 

回答

2

當你創建一個新的學生記錄您將要覆蓋的循環變量:

foreach (var student in Student) 
{ 
    using (var transaction = _context.Database.BeginTransaction()) 
    { 
     try 
     { 
      Student student = new Student... 

使用不同的變量名稱。

如果

在你的內心,主題信息,foreach循環你需要算成功的次數:

foreach (var student in Student) 
{ 
    using (var transaction = _context.Database.BeginTransaction()) 
    { 
     try 
     { 
      Student student = new Student... 

      int numSuccesses = 0; 
      foreach(var subjectInfo in subjectsInfo) 
      { 
       try 
       { 
        ... code omitted for clarity 

        numSuccesses++; // The very last thing you do 
       }  
       Catch(Exception ex) 
       { 
        // catch exception 
       } 
      } 
     } 

     Catch(Exception ex) 
     { 

     } 
    } 
} 

正如你只有真的要保存記錄,如果至少一個主題被插入你需要回滾學生記錄的插入,如果有在subjectsInfo環後沒有成功:

if (numSucesses == 0) 
{ 
    // Roll back the insertion of the student record 
} 

Additio最終,您應該只捕獲可以從中恢復的異常並記錄錯誤。有一個通用的異常處理程序通常是一個糟糕的設計的標誌。

+0

謝謝你的回答。我現在要試一試。爲什麼你建議在內部forEach循環之後移動學生記錄的saveChanges?我需要了解這一點。它會造成多大的差異?因爲我認爲/根據knowlede,我需要先保存學生記錄/內部foreach之前,以便我可以使用student.Id內部foreach循環。希望我能夠解釋你我的困惑點。 – simbada

+0

@simbada你自己說你不想保存學生記錄,如果他們的主題記錄都沒有保存,這個改變就完成了。 – ChrisF

+0

我的理解是(糾正我,如果我錯了),我必須在內部foreach(SubjectInfo ..)之前附加學生記錄到上下文,所以我可以使用/分配student.Id作爲FK到SubInfo。 saveChanges我們可以按照你所說的向下移動,但不是'_context.Student.Add(student);'它必須先於內心的預言。 – simbada

相關問題