我的Asp.Net MVC页面需要12秒。载入

时间:2014-06-27 02:05:46

标签: c# asp.net asp.net-mvc asp.net-mvc-4

我有一个像这样的MVC控制器

public ActionResult Index(int vendor=-1, int product = -1, string error="", string mode="Shortfall")
    {
        if (Session["UserId"] == null)
            return RedirectToAction("Index", "Login");
        var products = DbContext.GetAllProducts();
        List<SurplusViewModel> surplusList = new List<SurplusViewModel>();
        Dictionary<int, string> searchVendor = new Dictionary<int, string>();
        Dictionary<int, string> searchProds = new Dictionary<int, string>();
        if (products.Count() > 0)
        {
            foreach (var prod in products)
            {
                SurplusViewModel s = new SurplusViewModel(prod);
                surplusList.Add(s);
                foreach (var v in s.Vendors)
                {
                    if (!searchVendor.ContainsKey(v.CorpId))
                    {
                        searchVendor.Add(v.CorpId, v.CorpName);
                    }
                }
                if(!searchProds.ContainsKey(s.ProductId))
                    searchProds.Add(s.ProductId, s.ProductVM.ProductCode + " / " + s.ProductVM.ProductPartNo);
            }
        }
        ViewData["vendorList"] = searchVendor;
        ViewData["productList"] = searchProds;
        ViewData["selectVendor"] = vendor;
        ViewData["selectProd"] = product;
        ViewData["mode"] = mode;
        ViewBag.Message = "";
        ViewBag.Error = "";
        IEnumerable<SurplusViewModel> finalList = surplusList.OrderBy(o => o.Difference).ToList();
        if (vendor > 0)
        {
            Corporation searchcorp = DbContext.GetCorporation(vendor);
            finalList = finalList.Where(x => x.VendorNames.IndexOf(searchcorp.CorpName) >= 0);
        }
        if (product > 0)
        {
            finalList = finalList.Where(x => x.ProductId == product);
        }
        if (vendor < 0 && product < 0)
        {
            if (mode.Equals("Shortfall"))
                finalList = finalList.Where(f => f.VendorQuantity - (f.CMQuantity + f.OEMQuantity) < 0);
            else if (mode.Equals("Surplus"))
                finalList = finalList.Where(f => f.VendorQuantity - (f.CMQuantity + f.OEMQuantity) > 0);


        }
        return View(finalList);
        //return View();
    }

在localhost上加载大约需要20秒。我该怎么做才能改善我的应用程序的加载时间。如果在本地主机上需要20秒,我认为它在互联网上会非常慢。有什么建议吗?

编辑:SurplusViewModel的代码

public SurplusViewModel(Product product)
    {
        int productId = product.ProductId;
        ProductId = productId;
        ProductVM = new ProductViewModel(product);
        var saleDetsCM = from s in DbContext.GetSalesOrderDetailsFromCM()
                         where s.ProductId == productId && s.SaleStatus.Equals("Open") && (s.OrderType.ToLower().Equals("prototype") || s.OrderType.ToLower().Equals("production"))
                         orderby s.SalDetId descending
                         select s;

        var saleDetsOEM = from s in DbContext.GetSalesOrderDetailsFromOEMs()
                          where s.ProductId == productId && s.SaleStatus.Equals("Open") && (s.OrderType.ToLower().Equals("prototype") || s.OrderType.ToLower().Equals("production"))
                          orderby s.SalDetId descending
                          select s;

        var shipQty = from s in DbContext.GetAllSalesDets()
                      where s.ProductId == productId && !s.SaleStatus.Equals("Open") && (s.OrderType.ToLower().Equals("prototype") || s.OrderType.ToLower().Equals("production"))
                      orderby s.SalDetId descending
                      select s;

        CustomerOrdersFromCMs = saleDetsCM.ToList();
        CustomerOrdersFromOEMs = saleDetsOEM.ToList();
        VendorOrders = (from p in DbContext.GetPurchaseDetsForProduct(productId)
                        where p.OrderType != null && (p.OrderType.ToLower().Equals("prototype") || p.OrderType.ToLower().Equals("production"))
                        select p).ToList();
        var poIds = from v in VendorOrders
                     select v.PodPOId;
        BatchPurchaseDetails = DbContext.GetBatchPurchaseForProduct(productId).ToList();
        VendorOrderCount = 0;
        VendorQuantity = 0;
        var purchaseOrds = (from po in DbContext.GetPurchaseOrdersForProduct(productId)
                            where poIds.Contains(po.POId)
                            select po).ToList();
        List<int> vendIds = new List<int>();
        foreach (var po in purchaseOrds)
        {
            vendIds.Add(po.VendorId.Value);
        }
        var vendors = from v in DbContext.GetAllCorps()
                      where vendIds.Contains(v.CorpId)
                      select v;

        foreach (var podet in VendorOrders)
        {
            double totalbatchqty = 0;
            var purdetBatch = DbContext.GetBatchDetailsForPurchaseDet(podet.PodId);
            VendorQuantity += podet.Quantity;
            foreach (var b in purdetBatch)
            {
                totalbatchqty += b.Quantity;
                VendorQuantity -= b.Quantity;
            }
            if (totalbatchqty >= podet.Quantity)
            {

            }
            else
            {
                VendorOrderCount++;
            }

        }

        Vendors = vendors.ToList();
        VendorNames = "";
        foreach (var vnd in Vendors)
        {
            VendorNames += vnd.CorpName + ",";
        }
        if (VendorNames.Length > 0)
        {
            VendorNames = VendorNames.Substring(0, VendorNames.Length - 1);
        }


        OEMQuantity = 0;
        foreach (var item in CustomerOrdersFromOEMs)
        {
            OEMQuantity += item.Quantity;
        }

        CMQuantity = 0;
        foreach (var item in CustomerOrdersFromCMs)
        {
            CMQuantity += item.Quantity;
        }
        ShipQuantity = 0;
        foreach (var item in shipQty)
        {
            ShipQuantity += item.Quantity;
        }
        Difference = VendorQuantity - (CMQuantity + OEMQuantity);
        //TotalInsideSalesOrder = VendorOrders.Count();

    }

1 个答案:

答案 0 :(得分:3)

你犯了很多错误,或者至少非常糟糕。首先,您将从各种查询返回所有记录,并在内存中处理它们。如果只有少数记录,这很好,但你提到有50种产品。有多少供应商?有多少公司?

你正在做几个数据库查询,听起来你在实例化的子对象中做了更多的查询。所有这些查询都需要时间。这就是为什么你想通过编写更具包容性的单个查询来最小化查询,并在单个(或尽可能少的)查询中尽可能多地在sql server上执行工作。

您可以优化的区域...不要Count() > 0,而是使用.Any()。 .Any在找到的第一条记录后返回true,而不是必须计算所有内容,然后将该数字与0进行比较。

另一个领域,你正在foreach中做一个foreach。这会产生n * m个循环。也就是说,如果有2个产品和2个供应商,那就是4个循环,但如果它是3个循环,那么它是9个循环,如果它是4个循环,那么它是4个循环。如果它是每2500个循环中的50个。并且每个循环都执行你的SurplusViewModel构造函数,如果有很多代码就意味着它会变成sloooooooow。

我从您的更新中看到,SurplusViewModel至少执行了7次查询,可能更多......很难说。所以2500 * 7或17,500查询(假设50个产品,50个供应商)。你开始明白它为什么这么慢了吗?现在,想象一下,你有100个产品和100个供应商。这是10,000个循环,有7个以上的查询,这至少有70,000个查询。这不是一个可扩展的解决方案。

让我们进一步看看......所有这些“Getxxx”方法中有什么?我假设每个都有某种查询?您是否每次都可以执行双重查询?同样,您没有包含所有信息。

说实话,我很惊讶这只需要20秒......我认为任何数据量都会超过20分钟。