foreach更新对象中的值会覆盖值

时间:2014-10-20 18:46:28

标签: c# linq foreach iteration overwrite

警告:我知道这些代码的某些部分很糟糕,但它现在就是这样。我只是想让它正常运行。我完全打算稍后重构。我现在只需要一个正常工作的应用程序。

初始linq查询会抓取几个数据字段,但必须在结果集中的每个项目中添加更多数据。所以,我们有下面的foreach。它抓取数据并更新每一行。

它覆盖了我所想的一切,可能是foreach的最后一次迭代。为什么?如何防止覆盖?

请记住,工作变量只是一个句点ID。我想获得前一个或未来的时期,减去或添加到这个允许这个。

    public List<intranetGS.Forecast> getForecast(int branchId) {
        //user role protection here

        intraDataContext q = new intraDataContext();

        //this grabs the initial data
        var basefc = (from f in q.fc_items
                      where f.color_option == false
                      select new intranetGS.Forecast {
                          itemId = f.item_id,
                          item = f.item_number,
                          itemDesc = f.description,
                          itemSuffix = f.item_suffix,
                          itemPrefix = f.item_prefix,
                          designation = f.designation
                      });


        //now we filter
        switch (getDesignation(branchId)) {
            case 1:
                basefc = basefc.Where(n => n.designation != 3);
                basefc = basefc.Where(n => n.designation != 6);
                break;
            case 2:
                basefc = basefc.Where(n => n.designation > 3);
                break;
            case 3:
                basefc = basefc.Where(n => n.designation != 2);
                basefc = basefc.Where(n => n.designation != 6);
                break;
        }

        var current = Convert.ToInt32(DateTime.Now.Month);
        var working = 0;
        var year = Convert.ToInt32(DateTime.Now.Year);

        List<intranetGS.Forecast> res = new List<intranetGS.Forecast>(); 

        foreach (var f in basefc) {

            working = getPeriod(current + "/" + (year - 1)); //starting with last year;
            var ly = (from l in q.fc_forecasts where l.period == working && l.branch == branchId && l.item == f.itemId select l).FirstOrDefault();
            if (!object.ReferenceEquals(ly, null)) {
                f.lastYearForecast = ly.forecast;
                f.lastYearReceipt = ly.receipt;
            }

            working = getPeriod(current + "/" + year) - 2; //two months ago
            var m2 = (from l in q.fc_forecasts where l.period == working && l.branch == branchId && l.item == f.itemId select l).FirstOrDefault();
            if (!object.ReferenceEquals(m2, null)) {
                f.twoMosForecast = m2.forecast;
                f.twoMosReceipts = m2.receipt;
                f.twoMosUsage = m2.usage_lb;
            }

            working = getPeriod(current + "/" + year) - 1; //one month ago
            var m1 = (from l in q.fc_forecasts where l.period == working && l.branch == branchId && l.item == f.itemId select l).FirstOrDefault();
            if (!object.ReferenceEquals(m1, null)) {
                f.oneMosForecast = m1.forecast;
                f.oneMosReceipts = m1.receipt;
                f.oneMosUsage = m1.usage_lb;
            }

            working = getPeriod(current + "/" + year); //current month
            var m = (from l in q.fc_forecasts where l.period == working && l.branch == branchId && l.item == f.itemId select l).FirstOrDefault();
            if (!object.ReferenceEquals(m, null)) {
                f.currentMosForecast = m.forecast;
                f.currentMosReceipts = m.receipt;
                f.currentMosusage = m.usage_lb;
            }

            working = getPeriod(current + "/" + year) + 1; //one month from now
            var mnext1 = (from l in q.fc_forecasts where l.period == working && l.branch == branchId && l.item == f.itemId select l).FirstOrDefault();
            if (!object.ReferenceEquals(mnext1, null)) {
                f.plusOneForecast = mnext1.forecast;
                f.plusOneForecastId = mnext1.forcast_id;
            }

            working = getPeriod(current + "/" + year) + 2; //two months from now
            var mnext2 = (from l in q.fc_forecasts where l.period == working && l.branch == branchId && l.item == f.itemId select l).FirstOrDefault();
            if (!object.ReferenceEquals(mnext2, null)) {
                f.plusTwoForecast = mnext2.forecast;
                f.plusTwoForecastId = mnext2.forcast_id;
            }

        } //this is insanely and extremely cumbersome; refactor later.

        return basefc;
    }

更新:它不是一个列表,它需要是一个列表以避免覆盖。

1 个答案:

答案 0 :(得分:1)

问题是,当用户构建查询时,linq中会发生延迟执行,并且在内部构建一个可以添加新表达式的表达式树。在执行期间确定查询因子后,例如for循环中的可枚举目标或通过.ToList()该列表仍然是 fluid 。由于代码只是添加更多表达式而不是将其过滤到新列表中,因此查询增长了。

问题是在处理现有代码时,开发人员是否希望继续构建表达式树以获得性能,或者他们是否打算在流程的每个步骤中创建项目具体

您可能会通过使初始列表具体化来修复问题,但可能会在未来引入逻辑错误。记住这一点。