2015-07-29 3 views
1

Приложение, которое я создаю, позволяет пользователю загрузить CSV-файл, который в конечном итоге заполнит поля существующей таблицы SQL, где совпадают идентификаторы. Во-первых, я использую LinqToCsv и цикл foreach для импорта CSV во временную таблицу. Затем у меня есть другой цикл foreach, где я пытаюсь зациклить строки из временной таблицы в существующую таблицу, где совпадают идентификаторы.Пытаться получить доступ к переменной извне foreach loop

Действие контроллера, чтобы завершить этот процесс:

[HttpPost] 
public ActionResult UploadValidationTable(HttpPostedFileBase csvFile) 
{ 
    var inputFileDescription = new CsvFileDescription 
    { 
     SeparatorChar = ',', 
     FirstLineHasColumnNames = true 
    }; 
    var cc = new CsvContext(); 
    var filePath = uploadFile(csvFile.InputStream); 
    var model = cc.Read<Credit>(filePath, inputFileDescription); 

    try 
    { 
     var entity = new TestEntities(); 
     var tc = new TemporaryCsvUpload(); 
     foreach (var item in model) 
     { 

      tc.Id = item.Id; 
      tc.CreditInvoiceAmount = item.CreditInvoiceAmount; 
      tc.CreditInvoiceDate = item.CreditInvoiceDate; 
      tc.CreditInvoiceNumber = item.CreditInvoiceNumber; 
      tc.CreditDeniedDate = item.CreditDeniedDate; 
      tc.CreditDeniedReasonId = item.CreditDeniedReasonId; 
      tc.CreditDeniedNotes = item.CreditDeniedNotes; 
      entity.TemporaryCsvUploads.Add(tc); 
     } 

     var idMatches = entity.Authorizations.ToList().Where(x => x.Id == tc.Id); 

     foreach (var number in idMatches) 
     { 
      number.CreditInvoiceDate = tc.CreditInvoiceDate; 
      number.CreditInvoiceNumber = tc.CreditInvoiceNumber; 
      number.CreditInvoiceAmount = tc.CreditInvoiceAmount; 
      number.CreditDeniedDate = tc.CreditDeniedDate; 
      number.CreditDeniedReasonId = tc.CreditDeniedReasonId; 
      number.CreditDeniedNotes = tc.CreditDeniedNotes; 
     } 
     entity.SaveChanges(); 
     entity.Database.ExecuteSqlCommand("TRUNCATE TABLE TemporaryCsvUpload"); 

     TempData["Success"] = "Updated Successfully"; 

    } 
    catch (LINQtoCSVException) 
    { 
     TempData["Error"] = "Upload Error: Ensure you have the correct header fields and that the file is of .csv format."; 
    } 

    return View("Upload"); 
} 

Проблема в коде выше, что tc находится внутри первого цикла, но матчи определяются после цикла с var idMatches = entity.Authorizations.ToList().Where(x => x.Id == tc.Id);, так что я только получив последний элемент первого цикла.

Так что мне нужно поставить var idMatches = entity.Authorizations.ToList().Where(x => x.Id == tc.Id); в первый цикл, но тогда я не могу получить к нему доступ во втором. Если я вложу второй цикл, это способ замедлить работу. Есть ли способ, которым я мог бы поставить вышеуказанный оператор в первом цикле и все равно получить к нему доступ. Или любые другие идеи для достижения того же? Благодаря!

+0

Вы хотите дублировать строки, в которых идентификатор совпадает или только одна строка для каждого уникального идентификатора? –

+0

Поскольку строка для каждого уникального идентификатора – cfly24

ответ

0

Объявите idMatches перед первым циклом, но не создавайте его или не устанавливайте его значение null. Тогда вы сможете использовать его внутри обеих петель. После перемещения объявления до первого цикла вы все равно получите значения из последней итерации, используя простой Where. Вам нужно будет объединить уже существующий список с результатами для текущей итерации.

2

Вместо использования нескольких циклов отслеживайте обработанные идентификаторы по мере их поступления, а затем исключайте любые дубликаты.

[HttpPost] 
public ActionResult UploadValidationTable(HttpPostedFileBase csvFile) 
{ 
    var inputFileDescription = new CsvFileDescription 
    { 
     SeparatorChar = ',', 
     FirstLineHasColumnNames = true 
    }; 
    var cc = new CsvContext(); 
    var filePath = uploadFile(csvFile.InputStream); 
    var model = cc.Read<Credit>(filePath, inputFileDescription); 

    try 
    { 
     var entity = new TestEntities(); 
     var tcIdFound = new HashSet<string>(); 

     foreach (var item in model) 
     { 
         if (tcIdFound.Contains(item.Id)) 
         { 
          continue; 
         }     

      var tc = new TemporaryCsvUpload(); 
      tc.Id = item.Id; 
      tc.CreditInvoiceAmount = item.CreditInvoiceAmount; 
      tc.CreditInvoiceDate = item.CreditInvoiceDate; 
      tc.CreditInvoiceNumber = item.CreditInvoiceNumber; 
      tc.CreditDeniedDate = item.CreditDeniedDate; 
      tc.CreditDeniedReasonId = item.CreditDeniedReasonId; 
      tc.CreditDeniedNotes = item.CreditDeniedNotes; 

      entity.TemporaryCsvUploads.Add(tc); 
     } 

     entity.SaveChanges(); 
     entity.Database.ExecuteSqlCommand("TRUNCATE TABLE TemporaryCsvUpload"); 

     TempData["Success"] = "Updated Successfully"; 

    } 
    catch (LINQtoCSVException) 
    { 
     TempData["Error"] = "Upload Error: Ensure you have the correct header fields and that the file is of .csv format."; 
    } 

    return View("Upload"); 
} 

Если вы хотите, чтобы убедиться, что вы получите последнее значение для любых повторяющихся идентификаторов, а затем хранить каждый TemporaryCsvUpload запись в словаре вместо того, чтобы использовать только HashSet. Та же основная идея.

+0

Выглядит отлично, я должен был заметить, что идентификаторы являются уникальными varchars. – cfly24

+0

@CavanFlynn, нормально, это должно влиять только на объявление типа для 'HashSet'. –

Смежные вопросы