我有一個MVC/ASP.NET Web應用程序跟蹤員工信息,如StartDate,這是一個DateTime數據類型,員工在公司工作。Linq:按日期間隔分組(5,10,15等..年)
我們還在公司爲員工頒發時間獎,並希望在公司中分5,10,15,20,25,30年以上。
我該如何編寫一個Linq聲明,該聲明將僅由在公司時間已達到年度間隔基準(5,10,15等等)中的員工(人員)進行分組, 「時間在公司」獎?謝謝你的幫助。
我有一個MVC/ASP.NET Web應用程序跟蹤員工信息,如StartDate,這是一個DateTime數據類型,員工在公司工作。Linq:按日期間隔分組(5,10,15等..年)
我們還在公司爲員工頒發時間獎,並希望在公司中分5,10,15,20,25,30年以上。
我該如何編寫一個Linq聲明,該聲明將僅由在公司時間已達到年度間隔基準(5,10,15等等)中的員工(人員)進行分組, 「時間在公司」獎?謝謝你的幫助。
查看以下用於演示如何按期間/間隔進行分組的單元測試。
[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;
}
}
這個解決方案非常棒!通過您的解決方案,我掌握了您的主要邏輯,並進行了一些改變,我認爲其他人可能從中受益。絕對不可能以你的耐心來幫助你,並且我的專業知識與我正在努力完成的事情無關。
請參閱以下我的變化...
控制器
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>
你需要證明你已經嘗試一下,提供一些示例代碼。你有沒有搜索過答案,因爲我確信之前有人問過這個問題? – DavidG
@DavidG - 我一直在找東西,並沒有找到一個解決方案。我發現的那些是專門用於SQL(並且無法轉換爲linq),或者不適用於以前設置的靜態時間間隔。我唯一的示例代碼是查詢數據上下文以獲取在公司內部活動的人員(!EndDate.HasValue),以及由StartDate分組。我之前做過很多分組,之前沒有這樣的設置數據。 – Element808
@Nkosi - 遺憾的是,我的情況略有不同,因爲我只想要一個專門針對那些適合那個年份的人的專屬查詢。不是所有的人。 – Element808