2017-08-12 24 views
-3

我有一個MVC/ASP.NET Web應用程序跟蹤員工信息,如StartDate,這是一個DateTime數據類型,員工在公司工作。Linq:按日期間隔分組(5,10,15等..年)

我們還在公司爲員工頒發時間獎,並希望在公司中分5,10,15,20,25,30年以上。

我該如何編寫一個Linq聲明,該聲明將僅由在公司時間已達到年度間隔基準(5,10,15等等)中的員工(人員)進行分組, 「時間在公司」獎?謝謝你的幫助。

+1

你需要證明你已經嘗試一下,提供一些示例代碼。你有沒有搜索過答案,因爲我確信之前有人問過這個問題? – DavidG

+0

@DavidG - 我一直在找東西,並沒有找到一個解決方案。我發現的那些是專門用於SQL(並且無法轉換爲linq),或者不適用於以前設置的靜態時間間隔。我唯一的示例代碼是查詢數據上下文以獲取在公司內部活動的人員(!EndDate.HasValue),以及由StartDate分組。我之前做過很多分組,之前沒有這樣的設置數據。 – Element808

+0

@Nkosi - 遺憾的是,我的情況略有不同,因爲我只想要一個專門針對那些適合那個年份的人的專屬查詢。不是所有的人。 – Element808

回答

1

查看以下用於演示如何按期間/間隔進行分組的單元測試。

[TestClass] 
public class GroupByDateIntervalsTests { 
    [TestMethod] 
    public void Group_By_5_year_Intervals_Max_30() { 
     var employees = GenerateRandomDates(DateTime.Now, 5, 40, 50).Select((d, i) => new { id = i, StartDate = d }); 

     var now = DateTime.Today; 
     var period = 5; 
     var maxPeriod = 30; 
     var groups = from employee in employees 
        let interval = DateTime.MinValue.AddDays((now - employee.StartDate).TotalDays).Year/period 
        group employee by Math.Min(interval * period, maxPeriod) into g 
        orderby g.Key 
        select new { 
         period = g.Key, 
         employees = g.Select(e => e.id).ToArray() 
        }; 

     var result = groups.ToList(); 
    } 

    [TestMethod] 
    public void Group_By_Random_Interval_Max_30() { 
     var employees = GenerateRandomDates(DateTime.Now, 5, 40, 50).Select((d, i) => new { id = i, StartDate = d }); 

     var now = DateTime.Today; 
     var periods = new[] { 5, 10, 20, 30 }; 
     var groups = employees 
      .GroupBy(employee => { 
       var period = DateTime.MinValue.AddDays((now - employee.StartDate).TotalDays).Year; 
       var interval = periods.Where(p => (period/p) > 0).Max(); 
       return Math.Min(interval, periods.Max()); 
      }) 
      .Select(g => new { 
       period = g.Key, 
       employees = g.Select(e => e.id).ToArray() 
      }); 

     var result = groups.ToList(); 
    } 

    public List<DateTime> GenerateRandomDates(DateTime rootDate, int minAgeAtRootDate, int maxAgeAtRootDate, int count) { 
     Contract.Assert(minAgeAtRootDate <= maxAgeAtRootDate, "invalid age range. Minimum age cannot be higher than maximum age"); 
     var minDate = rootDate.Date.AddYears(-maxAgeAtRootDate); 
     var maxDate = rootDate.Date.AddYears(-minAgeAtRootDate); 
     var range = (maxDate - minDate).Days; 
     if (range == 0) { 
      range = 364; 
     } 
     var random = new Random(); 
     var dates = Enumerable 
      .Range(1, count) 
      .Select(i => minDate.AddDays(random.Next(range))) 
      .ToList(); 
     return dates; 
    } 
} 
1

這個解決方案非常棒!通過您的解決方案,我掌握了您的主要邏輯,並進行了一些改變,我認爲其他人可能從中受益。絕對不可能以你的耐心來幫助你,並且我的專業知識與我正在努力完成的事情無關。

請參閱以下我的變化...

控制器

public ActionResult LengthOfService() 
{ 
    ViewBag.Title = "Length of Service Awards Report"; 
    var people = db.People.ToList().Where(p => !p.EndDate.HasValue); 
    var now = DateTime.Today; 
    var period = 5; 
    var maxPeriod = 30; 
    var query = (from p in people 
       let interval = DateTime.MinValue.AddDays((now - p.LengthOfService).TotalDays).Year/period 
       where interval > 0 
       group p by Math.Min(interval * period, maxPeriod) into x 
       orderby x.Key 
       select new AwardInfo 
       { 
        Years = x.Key, 
        People = x 
       }).ToList(); 
    return View(query); 
} 

視圖模型

public class AwardInfo 
{ 
    public int Years { get; set; } 
    public IEnumerable<People> People { get; set; } 
} 

查看

@model List<CPR.Models.AwardInfo> 

<h2>@ViewBag.Title</h2> 

<table class="table table-responsive table-hover"> 
    <thead> 
     <tr> 

      <th class="col-sm-1">Service Award</th> 
      <th class="col-sm-2">Name</th> 
      <th class="col-sm-2">Date of Service</th> 
      <th class="col-sm-2">Company</th> 
     </tr> 
    </thead> 
    @foreach (var item in Model) 
    { 
     <tbody> 
      <tr> 
       <th class="panel-bg" colspan="5">@item.Years years</th> 
      </tr> 
     </tbody> 
     <tbody> 
      @foreach (var person in item.People) 
      { 
       <tr> 
        <td class="col-sm-1"></td> 
        <td class="col-sm-2">@person.LastName, @person.FirstName</td> 
        <td class="col-sm-2">@person.LengthOfService.ToShortDateString()</td> 
        <td class="col-sm-2">@person.Companies.Name</td> 
       </tr> 
      } 
     </tbody> 
    } 
</table> 

enter image description here