public List<KPISupplierReportShow> GetKPIReport
(bool? purchaseStatus,List<string> facs, List<string> status, List<string> types, string searchKey, string startDate, string endDate)
{
using (SRMDatabaseEntities entity = new SRMDatabaseEntities())
{
DateTime start = string.IsNullOrEmpty(startDate) ? DateTime.MinValue : Convert.ToDateTime(startDate);
DateTime end = string.IsNullOrEmpty(endDate) ? DateTime.MaxValue : Convert.ToDateTime(endDate);
var model = from p in entity.KPISupplierReport
join q in entity.SupplierInfoReport on p.SupplierCode equals q.SupplierCode
join j in entity.SystemUser on p.CreatedUser.ToUpper() equals j.UserId.ToUpper() into temp
from k in temp.DefaultIfEmpty()
where
(
status.Contains(p.Status)
&& facs.Contains(p.FactoryCode)
&& types.Contains(p.ReportCycle)
&& (purchaseStatus == null || q.PurchaseStatus == purchaseStatus)
&& (p.CreatedDate > start && p.CreatedDate < end)
&&
(string.IsNullOrEmpty(searchKey)
|| p.SupplierCode.Contains(searchKey)
|| p.SupplierName.Contains(searchKey)
|| p.ReportNumber.Contains(searchKey)
|| k.UserName.Contains(searchKey)
|| p.CreatedUser.Contains(searchKey)
|| p.ReportName.Contains(searchKey)
)
)
orderby p.Id descending
select new
{
q.PurchaseStatus,
p.Id,
p.ApprovalStatus,
p.CreatedDate,
k.UserName,
p.FactoryCode,
p.FactoryName,
p.FeedbackDate,
p.KPIMonthEnd,
p.KPIMonthStart,
p.KPIYear,
p.MaterielCode,
p.ReportCycle,
p.ReportName,
p.ReportNumber,
p.Score,
p.SendDate,
p.Status,
p.SupplierCode,
p.SupplierName
};
var modelList = model.ToList();
var numberList = modelList.Select(i => i.ReportNumber).ToList();
var itemList = entity.KPISupplierItem.Where(i => numberList.Contains(i.ReportNumber)).ToList();
//上面部分取數都是很快的,就是下面這部分要進行行列轉換,
//把明細里對應的列寫到頭的行里,測驗用10000條記錄,這個foreach大概要2分多鐘,
//除了修改超時時間限制,還有別的辦法么?
List<KPISupplierReportShow> reportList = new List<KPISupplierReportShow>();
KPISupplierReportShow rshow;
List<KPISupplierItem> tempItemList;
KPISupplierItem tempItem;
foreach (var kpi in modelList)
{
rshow = new KPISupplierReportShow()
{
PurchaseStatus=kpi.PurchaseStatus? "激活":"暫停",
ApprovalStatus = EnumHelper.GetEnumDescription<WorkflowStatus>(EnumHelper.GetEnum<WorkflowStatus>(kpi.ApprovalStatus)),
CreatedDate = kpi.CreatedDate.ToString("yyyy-MM-dd"),
CreatedUser = kpi.UserName,
FactoryCode = kpi.FactoryCode,
FactoryName = kpi.FactoryName,
FeedbackDate = kpi.FeedbackDate,
Id = kpi.Id,
KPIMonthEnd = kpi.KPIMonthEnd,
KPIMonthStart = kpi.KPIMonthStart,
KPIYear = kpi.KPIYear,
MaterielCode = kpi.MaterielCode,
ReportCycle = kpi.ReportCycle,
ReportName = kpi.ReportName,
ReportNumber = kpi.ReportNumber,
Score = kpi.Score,
SendDate = kpi.SendDate,
Status = EnumHelper.GetEnumDescription<ExaminationStatus>(EnumHelper.GetEnum<ExaminationStatus>(kpi.Status)),
SupplierCode = kpi.SupplierCode,
SupplierName = kpi.SupplierName
};
tempItemList = itemList.Where(t => t.ReportNumber == kpi.ReportNumber).ToList();
//品質
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key1));
if (tempItem != null)
{
rshow.Penalty1 = 0 - (tempItem.TargetScore - (tempItem.Score.HasValue ? tempItem.Score.Value : 0));
rshow.PenaltyRemark1 = tempItem.Reason;
}
//交付
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key2));
if (tempItem != null)
{
rshow.Penalty2 = 0 - (tempItem.TargetScore - (tempItem.Score.HasValue ? tempItem.Score.Value : 0));
rshow.PenaltyRemark2 = tempItem.Reason;
}
//服務
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key3));
if (tempItem != null)
{
rshow.Penalty3 = 0 - (tempItem.TargetScore - (tempItem.Score.HasValue ? tempItem.Score.Value : 0));
rshow.PenaltyRemark3 = tempItem.Reason;
}
//附加運費
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key4));
if (tempItem != null)
{
rshow.Penalty4 = 0 - (tempItem.TargetScore - (tempItem.Score.HasValue ? tempItem.Score.Value : 0));
rshow.PenaltyRemark4 = tempItem.Reason;
}
//體系
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key5));
if (tempItem != null)
{
rshow.Penalty5 = 0 - (tempItem.TargetScore - (tempItem.Score.HasValue ? tempItem.Score.Value : 0));
rshow.PenaltyRemark5 = tempItem.Reason;
}
//成本
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key6));
if (tempItem != null)
{
rshow.Penalty6 = 0 - (tempItem.TargetScore - (tempItem.Score.HasValue ? tempItem.Score.Value : 0));
rshow.PenaltyRemark6 = tempItem.Reason;
}
//技術
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key7));
if (tempItem != null)
{
rshow.Penalty7 = 0 - (tempItem.TargetScore - (tempItem.Score.HasValue ? tempItem.Score.Value : 0));
rshow.PenaltyRemark7 = tempItem.Reason;
}
//----add by chenyuyi on 2018-09-10 begin----
//加分項
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key8));
if (tempItem != null)
{
rshow.Penalty8 = 0 - (tempItem.TargetScore - (tempItem.Score.HasValue ? tempItem.Score.Value : 0));
rshow.PenaltyRemark8 = tempItem.Reason;
}
//風險
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key9));
if (tempItem != null)
{
rshow.PenaltyRemark9 = tempItem.Reason;
}
//紅線
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key10));
if (tempItem != null)
{
rshow.PenaltyRemark10 = tempItem.Reason;
}
//----add by chenyuyi on 2018-09-10 end----
reportList.Add(rshow);
}
return reportList;
}
}
uj5u.com熱心網友回復:
1 考慮在資料庫行轉列,而不是程式里。2 你跟蹤過linq生成的sql陳述句嗎?看一下有沒有優化空間。
uj5u.com熱心網友回復:
而且,必定要1W條資料顯示出去嗎?uj5u.com熱心網友回復:
這個看著就比較頭疼了。首先,LinQ本身有自己的性能劣勢,不適合這種大資料量遍歷查找,比如:
tempItemList = itemList.Where(t => t.ReportNumber == kpi.ReportNumber).ToList();
itemList可以定義為一個以ReportNumber為Key,List<T>為Value的Dictionary<T1,List<T2>>,利用Hash的優勢,會吃點記憶體,但是提升查找效率。
//品質
tempItem = tempItemList.FirstOrDefault(t => t.Title.Contains(KPISupplierReportShow.Key1));
諸如此類的Contains,效率都不會太高,如果你的Key1...KeyN都是固定值,那我還是建議你把它們做成Dictionary的Key。否則的話,會比較難搞。
另外資料量龐大的話,如果正常情況就是1W甚至更多條資料需要同時遍歷的話,也建議去開辟多執行緒處理。
uj5u.com熱心網友回復:
是否可以在資料庫轉換,大資料展示可否分頁展示處理,這要效果會快uj5u.com熱心網友回復:
很明顯瓶頸在 EF(Entity Framework) 上。在復雜的場景,EF 效率低下。原因是復雜場景下,微軟對 EF 到資料庫 SQL 之間的優化沒有搞好,還不如手寫 SQL 陳述句快。如果先把資料查詢出來再使用 Linq 處理會快很多,但注意大資料量時查詢耗時比資料處理耗時要多很多。uj5u.com熱心網友回復:
加個stopwatch,看看哪里慢。我看回圈里用到了反射,這可能效率不高。EnumHelper.GetEnumDescription......
uj5u.com熱心網友回復:
試試 Parallel.ForEachuj5u.com熱心網友回復:
顯示沒問題,我做了分頁,至對查詢頁資料進行處理。
這是匯出到Excel報表用的。
另外,ReportNumber是主表的主鍵,明細表的外鍵
uj5u.com熱心網友回復:
你這關鍵是這10000+的回圈。能不能去掉呢?讀資料回傳的物體類,就是報表類,資料處理,可以放著報表類作處理,增加欄位,但又是不是全部能轉換成功呢?功能都完成不了,還優化效率,此其一,其二是改動非常大,又決心動手嗎?
uj5u.com熱心網友回復:
小范圍的改動,那就是回圈體中,代碼越少越快,或者斷點跟蹤,回圈體哪的代碼運行時間長,想辦法把它移到回圈體外。uj5u.com熱心網友回復:
你既然做了分頁,那為何還要一下子拿這么多出來?
根據currentPage和pageSize。分批拿取就沒加載慢的問題了。
uj5u.com熱心網友回復:
它這個是全部資料匯入到Excel慢轉載請註明出處,本文鏈接:https://www.uj5u.com/net/89061.html
標籤:C#
上一篇:你好,我最近在看這本書 Visual C# 2005從入門到精通,需要書里的練習檔案源代碼,你能提供給我嗎?
下一篇:C# 獲取單元格公式
