МОЯ Asp.Net Страница MVC занимает 12 секунд. для загрузки

#c# #asp.net #asp.net-mvc #asp.net-mvc-4

#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 amp;amp; 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 amp;amp; s.SaleStatus.Equals("Open") amp;amp; (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 amp;amp; s.SaleStatus.Equals("Open") amp;amp; (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 amp;amp; !s.SaleStatus.Equals("Open") amp;amp; (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 amp;amp; (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. это 12 секунд или 20 секунд? Это первая загрузка или последующие загрузки страницы?

2. Ваш контроллер удаляет ваш DbContext? Также вы можете использовать секундомер, чтобы определить, где находится узкое место?

3. Пожалуйста, выполните отладку с помощью функции вашего контроллера выше и определите самый длинный оператор. Если вы опубликуете эту строку, мы, скорее всего, сможем ответить на ваш вопрос.

4. @Erik Funkenbusch Иногда 12 секунд, иногда 20 секунд

5. Также, сколько у вас продуктов? ваш код загружает все продукты, возможно, лучше реализовать подкачку?

Ответ №1:

Вы делаете кучу вещей неправильно или, по крайней мере, очень плохо. Сначала вы возвращаете все записи из различных запросов, обрабатывая их в памяти. Это нормально, если записей всего несколько, но вы упоминаете, что существует 50 продуктов. Сколько поставщиков? Сколько корпораций?

Вы выполняете несколько запросов к базе данных, и похоже, что вы выполняете еще больше запросов в создаваемых вами подобъектах. Все эти запросы требуют времени. Вот почему вы хотите минимизировать запросы, написав более полные отдельные запросы и выполнив как можно больше работы на сервере sql в одном (или как можно меньшем количестве) запросов.

Области, которые вы можете оптимизировать… Не делайте Count() > 0 , вместо этого используйте .Any() . .Any возвращает true после первой найденной записи, вместо того, чтобы считать все, а затем сравнивать это число с 0 .

В другой области вы выполняете foreach внутри foreach . Это создает n * m циклов. т.Е., если есть 2 продукта и 2 поставщика, это 4 цикла, но если по 3 каждого, это 9 циклов, если по 4 каждого, это 16 циклов. если это 50 из каждых 2500 циклов. И каждый из этих циклов выполняет ваш конструктор SurplusViewModel, который, если в нем много кода, означает, что он будет slooooooow.

Из вашего обновления я вижу, что SurplusViewModel выполняет не менее 7 запросов, а может и больше.. трудно сказать. итак, это 2500 * 7 или 17 500 запросов (при условии, что 50 продуктов и 50 поставщиков). Вы начинаете понимать, почему это так медленно? Теперь представьте, что у вас было 100 продуктов и 100 поставщиков. Это 10 000 циклов с более чем 7 запросами, то есть не менее 70 000 запросов. Это не масштабируемое решение.

Давайте посмотрим дальше.. что во всех этих методах «Getxxx»? Я предполагаю, что в каждом из них есть какой-то запрос? Возможно, вы каждый раз выполняете двойные запросы? Опять же, вы не включаете всю информацию.

Честно говоря, я очень удивлен, что это занимает ВСЕГО 20 секунд… я бы подумал, что это будет больше похоже на 20 минут с любым объемом данных.

Комментарии:

1. SurplusViewModel — сложный объект (как вы можете видеть), в нашей команде мы решили ничего не запрашивать повторно, чтобы избежать обработки. Ваша точка зрения о foreach — это то, что я рассматриваю, возможно, для ее изменения. Здесь нет никаких повторных запросов, в которых я уверен. Но да, данные могут быть большими

2. @progrAmmar — Конечно, кажется, что вы выполняете много запросов, но опять же, поскольку вы не включили весь код, мы не можем узнать. Вы хотите сказать DbContext.GetSalesOrderDetailsFromCM() , что не запрашивает базу данных?

3. Это так, но это происходит только один раз в ViewModel:-S… Было бы лучше, если бы мы получили всю таблицу из базы данных, а затем выполнили все операции ‘WHERE’ в ViewModel?

4. @progrAmmar — Да, он делает это один раз в ViewModel, но вы создаете 50 ViewModels (или сколько бы продуктов у вас ни было), каждый из которых выполняет эти запросы каждый раз. Вы все еще не поняли сути. Вы должны делать все это в базе данных, а не в своем коде.

5. очевидно, что очень активная и быстрая загрузка данных. Вероятно, у вас очень быстрая машина для разработки, которая загружает тонны за 12 секунд при ответе на 1 запрос, но развернутая будет непригодна для использования. Я предлагаю вам, ребята, вернуться к чертежной доске и прочитать несколько статей о производительности интерактивных веб-приложений, не указанных в MVC, и изучить некоторые шаблоны проектирования.