2012-06-27 117 views
1

我遇到此LINQ查詢的性能問題。 這些數據已經包含到this.students中。 現在當我調用GetStudentData函數說1000倍時,它有巨大的開銷。平均 5.6秒:通過它10000次,我原來的版本循環優化此LINQ查詢

原始版本時 是否有改善這一點沒有改變LINQ到環路

public Student GetStudentData() 
    {   
      IEnumerable<Students> studentTypes = this.students.Where(x => (x.studentsId == studentId && x.StduentType.Equals(studentType))); 
      if(studentTypes.Count==0) return new Student() { studentid=studentID}; 
      return (Student)studentTypes.First(); 
    } 

所以在這裏的一種方式是結果新版本@沙漠的代碼FirstOrDefault:3.6秒

+0

你真的在運行這個1000嗎?否則,這篇文章是相當合適的:http://www.hanselman.com/blog/BackToBasicsYouArentSmarterThanTheCompilerPlusFunWithMicrobenchmarks.aspx – Killnine

+0

ew,作爲一邊,我真的不喜歡你如何返回一個新的學生,如果沒有符合條件是發現 - 很混亂。 – Didaxis

+0

是的,我正在運行這1000次 – abbas

回答

4

當您使用Where您遍歷所有記錄其是否履行給定條件下,當您使用First你只需要搜索第一個記錄滿足條件,所以使用First應該加快速度。

public Student GetStudentData() 
{   
    // get first student by id and type, return null if there is no such student 
    var student = students.FirstOrDefault(i => i.studentsId == studentId && i.StudentType.Equals(studentType)); 

    // if student is null then return new student 
    return student ?? new Student(); 
} 
+0

可能會簡化代碼,但沒有優化 – Didaxis

+0

@ErOx檢查我更新的答案,'First'應該比'Where'更快,因爲它不會檢查所有記錄... – Zbigniew

+0

好的解釋...讓我測試並看到結果 – abbas

2

那麼,問題恰恰就是您在循環中調用此方法,據說是1000次!

爲什麼不更改方法來接收studentID列表並一次返回1000個學生?喜歡的東西

var studentTypes = from c in this.students 
        where studentIDs.Contains(c.StudentID) 
        select c; 

哪裏studentIDs可以包含要學生ID列表的int[]

+0

我認爲這是正確的軌道 - 看起來需要在OP的邏輯中進行一些重構 – Didaxis

+0

Nopes ...這是用不同的參數調用的......這只是真實函數的一個簡單版本...所以它很容易理解。 – abbas

0

重構代碼,以便this.studentsDictionary<int, Student>(關鍵是StudentId),那麼同樣重新實現你的方法,以這樣的:

public Student GetStudentData(int studentId, StudentType studentType) { 
    Student result; 
    if (this.students.TryGetValue(studentId, out result)) 
     if (result.StudentType.Equals(studentType))) 
      return result; 
    return new Student { StudentId = studentId }; 
} 

如果你絕對不能重構this.students,您可以始終保持字典在平行

或者,您可以簡單地在1000迭代循環之前創建一個臨時字典(this.students.ToDictionary(student => student.StudentId))。