在C#中使用虚拟集合提高代码效率

在C#中使用虚拟集合提高代码效率,c#,sql,asp.net-mvc,linq,C#,Sql,Asp.net Mvc,Linq,你好,我有一个像这样的模型 public class Site { public int ID { get; set; } public string Name { get; set; } public string Address { get; set; } public string City { get; set; } public string Province { get; set; }

你好,我有一个像这样的模型

  public class Site
    {
        public int ID { get; set; }

        public string Name { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Province { get; set; }
        public string PostalCode { get; set; }

        public virtual ICollection<OffSiteItemDetails> ItemDetails { get; private set; }
        public virtual ICollection<SalesOrder> soDetails { get; private set; }
        public virtual ICollection<SODetails> SODDetails { get; private set; }

        public string IncomingTotalOSI(Site s)
        {
            PIC_Program_1_0Context db = new PIC_Program_1_0Context();
            float? partCost = 0;
            float? componentCost = 0;
            float? itemCost = 0;
            float? incomingCost = 0;
            List<OffSiteItemDetails> d = ItemDetails.Where(x => x.siteID == s.ID).ToList();


            var less30days = DateTime.Now.AddDays(-30);
            //List<SalesOrder> so = soDetails.Where(x => x.OrderType == SOType.OffSiteInventory).Where(x => x.DateCreated > less30days).ToList();
            List<SalesOrder> so = db.SalesOrders.Where(x => x.OrderType == SOType.OffSiteInventory).Where(x => x.DateCreated > less30days).ToList();
            List<SODetails> sod = db.SODetails.Where(x => x.SiteID == s.ID).ToList();

       foreach (var order in so)
        {

            foreach (var details in sod)
            {

                if (order.ID == details.SalesOrderID)
                {

                    if (details.PartID != null){
                        partCost += details.part_qty * db.Parts.Where(x => x.ID == details.PartID).FirstOrDefault().AveCostPerUnit;
                    }
                    else if (details.ComponentID != null){
                        componentCost += details.comp_qty * db.Components.Where(x => x.ID == details.ComponentID).FirstOrDefault().AveCostPerUnit;
                    }
                    else{
                        itemCost += details.item_qty * db.Items.Where(x => x.ID == details.ItemID).FirstOrDefault().CostPerUnit;
                    }
                }

            }
        }
        incomingCost = partCost + componentCost + itemCost;

            string cost = String.Format("{0:C}", incomingCost);

            return cost;
        }
  }
公共类站点
{
公共int ID{get;set;}
公共字符串名称{get;set;}
公共字符串地址{get;set;}
公共字符串City{get;set;}
公共字符串省{get;set;}
公共字符串PostalCode{get;set;}
公共虚拟ICollection ItemDetails{get;private set;}
公共虚拟ICollection所需详细信息{get;private set;}
公共虚拟ICollection SODDetails{get;private set;}
公共字符串输入(站点s)
{
PIC_程序_1_0上下文db=新PIC_程序_1_0上下文();
浮动?部分成本=0;
浮动?组件成本=0;
浮动?项目成本=0;
浮动?收入成本=0;
List d=ItemDetails.Where(x=>x.siteID==s.ID).ToList();
var less30days=DateTime.Now.AddDays(-30);
//List so=soDetails.Where(x=>x.OrderType==SOType.OffSiteInventory).Where(x=>x.DateCreated>less30天).ToList();
列出so=db.SalesOrders.Where(x=>x.OrderType==SOType.OffSiteInventory).Where(x=>x.DateCreated>less30天).ToList();
List sod=db.SODetails.Where(x=>x.SiteID==s.ID).ToList();
foreach(so中的var顺序)
{
foreach(sod中的var详细信息)
{
if(order.ID==details.SalesOrderID)
{
if(details.PartID!=null){
partCost+=details.part\u数量*db.Parts.Where(x=>x.ID==details.PartID).FirstOrDefault().AveCostPerUnit;
}
else if(details.ComponentID!=null){
componentCost+=details.comp_qty*db.Components.Where(x=>x.ID==details.ComponentID).FirstOrDefault().AveCostPerUnit;
}
否则{
itemCost+=details.item_数量*db.Items.Where(x=>x.ID==details.ItemID).FirstOrDefault().CostPerUnit;
}
}
}
}
收入成本=部件成本+部件成本+项目成本;
string cost=string.Format(“{0:C}”,incomingCost);
退货成本;
}
}

但这是低效的,因为它在同一数据集上循环多次。添加的订单越多,程序的运行速度就会越慢。我仍在学习MVC,并研究过虚拟收藏,但我仍不清楚如何在这种情况下使用它来提高程序的效率。首先,我建议从此行中删除
.ToList()

List sod=db.SODetails.Where(x=>x.SiteID==s.ID).ToList()

当您在那里使用ToList()时,您将强制在该点对基础数据存储执行和枚举,而不是推迟执行,直到您实际需要枚举所需的结果

然后更改以下行:

foreach(sod中的var详细信息)

致:

foreach(变量详细信息在db.SODetails中
。其中(x=>x.SiteID==s.ID&&details.SalesOrderID==order.ID))

当然,折衷的办法是,您通过查询每个销售订单来访问数据库,但您不会对同一数据进行多次迭代

您还可以去掉最内部循环中的if()语句,只需将您的条件放在Linq中,以限制所循环的内容。这也可以提高性能:


foreach(sod.Where(detail=>detail.SalesOrderID==order.ID)中的变量详细信息)

您调用的每个LINQ方法都会迭代整个
IEnumerable
。可能会从
foreach
更改为
for
,并在循环期间临时缓存值?我真的不知道,我不经常使用LINQ,因为这样的事情。请包括销售订单和销售订单详细信息模型。我相信你是一对多连接的?为什么销售订单不属于一个站点?如果父实体属于一个站点不是更好吗?假设你使用的是LINQ to SQL(而不是EF 6/EF Core),您可以使用
Join
返回销售订单及其详细信息,这样您就不必为每个
so
搜索
sod
。或者,使用
ToLookup
sod
转换为查找,这样您就可以直接获得销售订单的详细信息。