2017-05-26 152 views
0

我周圍環繞僱員&每個員工循環爲所有日期一個月。過濾大集合

我已經從Db預裝了一個列表ShiftDetails以改善性能。

foreach (var item in lstEmp) 
{ 
    while (fDate <= ToDate) 
    { 
    var employeeShifts = ShiftDetails 
     .Where(a => a.EmployeeId == item.Id && a.ShiftDate == fDate) 
     .Select(a => a) 
     .FirstOrDefault(); 
    } 
} 

當我用Profiler檢查性能時,上面的代碼行正在吃掉很大的時間。

有什麼辦法可以提高我的代碼的性能嗎?

我已經搜索&發現字典是最好的解決這個,但他們應該有唯一的鍵,在我的情況下,我沒有列表中的任何獨特的列。

+0

您可以使用[Parallel.Foreach](https://msdn.microsoft.com/en-us/library/dd460720(v = vs.110).aspx)方法加速嗎? – ckruczek

+0

你多久增加'fDate'變量?它是'DateTime'對象還是一些時間戳?迭代每毫秒可能比LINQ到3000個對象更痛苦 – hmnzr

+0

它是DateTime對象,對於每個員工迭代一個月,例如, 1April-30APril。 – Anup

回答

0

從我看到EmployeeId &的組合ShiftDate可能是您唯一的密鑰。

嘗試使用這樣的手工打造關鍵:

var key = EmployeeId.ToString() + " - " + a.ShiftDate.ToString(); 

那麼您的搜索將是一個簡單的一行:

if (myDictionary.ContainsKey(key)) 
{ 
// .. do your logic here 
} 
0

這個怎麼解決辦法:

foreach (var item in lstEmp) 
{ 
    var employeeShifts = ShiftDetails 
     .Where(a => a.EmployeeId == item.Id && isInDate(a.ShiftDate)) 
     .Select(a => a) 
     .FirstOrDefault(); 
} 

在代碼中的任何其他地方:

public bool isInDate(date start, date end, date dateFromUserProperty){ 
    //if dateFromUserProperty is within the range (start - end date) return true, 
    //else return false 
} 

你能解釋一下什麼是物品嗎?你是否想要獲得項目收集和你的用戶集合之間的交集?

0

我想你的操作分成兩個步驟:每個EmployeeId

    • 篩選輪班鑑於過濾變化,過濾器由第一ShiftDate


    通過篩選while循環之外的10個更快,因爲我們只計算一次該結果,而不是每月的每個日期。將結果保存爲List也使我們獲得了輕微的性能增益,因爲我們可以使用List.Find(它返回給定謂詞的第一個匹配值,並針對List s進行優化)而不是Where/FirstOrDefault

    foreach (var item in lstEmp) 
    { 
        var shiftsByEmployeeId = ShiftDetails.Where(a => a.EmployeeId == item.Id).ToList(); 
        while (fDate <= ToDate) 
        { 
         var employeeShifts = shiftsByEmployeeId.Find(a => a.ShiftDate == fDate); 
        } 
    }