设置属性时For Each循环的替代方法

时间:2016-01-13 20:17:30

标签: c# asp.net-mvc performance linq foreach

我在ASP.NET MVC应用程序中遇到了一些性能问题。我有一个列表,我需要设置几个属性。我的代码通过for循环读取列表,并根据记录日期值设置这两个属性。

以下是代码:

//Build City Taxes List
var cityTaxInformationList = (from citycigtax ct in db.citycigtaxes
                                join statecigtax st in db.statecigtaxes on ct.stateid equals st.stateid
                                join transaction tr in db.transactions on ct.masterkey equals tr.masterkey
                                select new CityViewModel
                                {
                                    CityMasterKey = ct.masterkey,
                                    StateShortName = st.stateshortname,
                                    CityName = ct.cityname,
                                    TransactionStickTax = tr.sticktax,
                                    TransactionDateStamp = tr.datestamp,
                                    TransactionEffectiveDate = tr.effdate,
                                    TransactionKey = tr.transactionkey,
                                    IsHighestDate = false,
                                    SecondCityRates = null,
                                    RateCount = 0
                                }).ToList();

var topCityTaxes = cityTaxInformationList.GroupBy(x => x.CityMasterKey, (Key, grp) => grp.OrderByDescending(y => y.TransactionEffectiveDate).First()).ToList();

foreach (var tx in cityTaxInformationList)
{
    tx.IsHighestDate = topCityTaxes.Exists(x => x.TransactionEffectiveDate == tx.TransactionEffectiveDate && x.CityMasterKey == tx.CityMasterKey);
    if (tx.IsHighestDate == true)
    {
        tx.RateCount = cityTaxInformationList.Where(x => x.IsHighestDate == false && tx.CityMasterKey == x.CityMasterKey).Select(x => x.TransactionStickTax).Count();
        tx.SecondCityRates = string.Join(", ", cityTaxInformationList.Where(x => x.IsHighestDate == false && tx.CityMasterKey == x.CityMasterKey)
            .Select(x => String.Format("{0:0.00000}", x.TransactionStickTax + " " + "(" + String.Format("{0:M/d/yyyy}", x.TransactionEffectiveDate) + ')')));

        if (tx.SecondCityRates == "")
        {
            tx.SecondCityRates = "None";
        }
    }
}

var TopCityTaxInformationList = cityTaxInformationList.GroupBy(x => x.CityMasterKey, (Key, grp) => grp.OrderByDescending(y => y.TransactionEffectiveDate).First()).ToList();

return TopCityTaxInformationList;

有更有效的方式执行此操作吗?我正在查看一份包含80,000条记录的列表,并循环显示每条记录,每一条记录都是破碎性能。

2 个答案:

答案 0 :(得分:4)

for循环没有破坏您的性能,使用topCityTaxes进行查找。它会查看整个列表以查找值(3次!!)。将topCityTaxes切换到字典,按CityMasterKey键入并进行查找。

答案 1 :(得分:1)

问题不在于foreach循环,而是循环内部的内部 - 对整个列表进行了大量无效的LINQ查询。

看看你在里面做什么以及你从函数中返回什么,你甚至不需要@Kyle W建议的查找结构,你只需要一个正确的处理算法

这是IMO相当于你正在做的事情

//Build City Taxes List
var cityTaxInformationList = ...;
// Build and return Top City Tax Information List
var topCityTaxInformationList = cityTaxInformationList.GroupBy(x => x.CityMasterKey, (key, elements) =>
{
    var elementList = elements.OrderByDescending(e => e.TransactionEffectiveDate).ToList();
    var first = elementList[0];
    first.IsHighestDate = true;
    first.RateCount = elementList.Count - 1;
    first.SecondCityRates = first.RateCount == 0 ? "None" : string.Join(", ",
         elementList.Skip(1).Select(x => string.Format("{0:0.00000} ({1:M/d/yyyy})",
             x.TransactionStickTax, x.TransactionEffectiveDate)));
    return first;
}).ToList();

return topCityTaxInformationList;

原理是原始代码中的所有逻辑都是针对共享相同CityMasterKey的元素,而GroupBy完全为您分离。