2014-04-25 17 views
1

我有一個如下的控制器,它需要太長時間加載數據。我正在使用contains和tolist()方法。我聽說過toList()方法的低性能。什麼是toList()方法的性能替代。

我怎樣才能改變這種方法更好的性能編碼。

public List<decimal> GetOrgSolution() 
{ 
    //Need to use USER id. but we have EMPNO in session. 
    var Users = db.CRM_USERS.Where(c => c.ID == SessionCurrentUser.ID || RelOrgPerson.Contains(c.EMPNO.Value)).Select(c => c.ID); 

    //Get the organization list regarding to HR organization 
    var OrgList = db.CRM_SOLUTION_ORG.Where(c => c.USER_ID == SessionCurrentUser.ID || Users.Contains(c.USER_ID.Value)).Select(c => c.ID).ToList(); 

    //Get related solutions ID with the OrgList 
    List<decimal> SolutionList = db.CRM_SOLUTION_OWNER.Where(p => OrgList.Contains(p.SOLUTION_ORG_ID.Value)).Select(c => (decimal)c.SOLUTION_ID).Distinct().ToList(); 

    return SolutionList; 
} 
+0

請參閱[使用ToList()時是否會影響性能?](http://stackoverflow.com/questions/15516462/is-there-a-performance-impact-when-calling-tolist)。 – mason

+0

最簡單的事情就是簡單地刪除「ToList()」,儘管這可能會或可能不會解決您的問題。調用ToList()會導致整個IEnumerable/IQueryable立即解析而不是懶惰地解析。 – Casey

回答

3

您可以通過將orglist查詢中刪除ToList()來加快速度。這使用延遲執行,而不是拉取組織列表的所有記錄。但是,如果在調用Contains()的查詢中沒有匹配,則它仍然必須加載所有內容。

public List<decimal> GetOrgSolution() 
{ 
    //Need to use USER id. but we have EMPNO in session. 
    var Users = db.CRM_USERS.Where(c => c.ID == SessionCurrentUser.ID || RelOrgPerson.Contains(c.EMPNO.Value)).Select(c => c.ID); 

    //Get the organization list regarding to HR organization 
    var OrgList = db.CRM_SOLUTION_ORG.Where(c => c.USER_ID == SessionCurrentUser.ID || Users.Contains(c.USER_ID.Value)).Select(c => c.ID); 

    //Get related solutions ID with the OrgList 
    List<decimal> SolutionList = db.CRM_SOLUTION_OWNER.Where(p => OrgList.Contains(p.SOLUTION_ORG_ID.Value)).Select(c => (decimal)c.SOLUTION_ID).Distinct().ToList(); 

    return SolutionList; 
} 
+0

另外我得到像SolutionList.departmant.Name這樣的視圖的一些信息,我應該使用包含方法來加載更好的加載時間? – umki

+0

我不認爲從Contains改變爲Any是必要的。 –

+0

@JeremyCook - 你說得對。我的腦海裏只有'IList'擁有'Contains'。對我感到羞恥。 –

2

除非你正在使用的列表是真正巨大的,它是極不可能的調用ToList是在你的代碼中的主要瓶頸。我更傾向於懷疑數據庫(假設您正在執行LINQ到SQL)。或者,您的嵌入式Contains調用。你有,例如:

db.CRM_SOLUTION_ORG..Where(
    c => c.USER_ID == SessionCurrentUser.ID || Users.Contains(c.USER_ID.Value)) 

所以對於db.CRM_SOLUTION_ORG失敗對SessionCurrentUser測試每一個項目,你會做一個順序搜索的Users名單。

想一想,因爲Users是懶惰的評估,你會在每次撥打Users.Contains時執行Users查詢。在這種情況下,如果您在Users上調用ToList(),看起來您的代碼效率會更高。這樣查詢只執行一次。

而且你可能應該保留ToList()OrgList查詢。否則,您每次撥打OrgList.Contains時都會重新執行該查詢。

也就是說,如果UsersOrgList可能有很多的項目,那麼你會更好,把他們變成HashSet這麼說你得到O(1)查找,而不是爲O(n)查找。

但看着你的代碼,看起來你應該能夠用一個單一的查詢來完成所有這些工作,並讓數據庫服務器來處理它。我對LINQ to SQL或您的數據模型肯定不夠了解,但從我的立場來看,它確實看起來像是三個表的簡單連接。

相關問題