我有一个像这样的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();
}
答案 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分钟。