试图从外部foreach循环访问变量

时间:2015-07-29 17:39:12

标签: c# sql asp.net-mvc entity-framework loops

我正在构建的应用程序允许用户上传.csv文件,该文件最终将填充Ids匹配的现有SQL表的字段。首先,我使用LinqToCsv和foreach循环将.csv导入临时表。然后我有另一个foreach循环,我试图将临时表中的行循环到Ids匹配的现有表中。

控制器完成此过程的操作:

[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);,但是在第二个循环中我无法访问它。如果我嵌套第二个循环,那么它是缓慢的方式。有什么办法可以将上面的语句放在第一个循环中并仍然可以访问它。或者任何其他想法来完成同样的事情?谢谢!

2 个答案:

答案 0 :(得分:2)

不要使用多个循环,而是随时跟踪已处理的ID,然后排除任何重复项。

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

如果要确保获取任何重复ID的最后一个值,请将每个TemporaryCsvUpload记录存储在字典中,而不是仅使用HashSet。同样基本的想法。

答案 1 :(得分:0)

在第一个循环之前声明idMatches,但不要实例化它或将其值设置为null。然后你就可以在两个循环中使用它了。在第一个循环之前移动声明之后,您仍将使用简单的Where获得上次迭代的值。您需要将现有列表与当前迭代的结果连接起来。

相关问题