使用 LINQ 创建特定数据集
Creating a specific dataset with LINQ
我无法从通过 Dapper 从数据库中获取的对象列表创建一个特定的“数据集”。所以事情是关于公司的日常出勤,所以用户来了,点击,出去,点击,我们有一个 table 行,如下所示:
sql table
所以我有一个像这样的模型 class:
public class Attendance
{
public int UserId { get; set; }
public string FullName { get; set; }
public DateTime DateTimeUtcIn { get; set; }
public DateTime DateTimeUtcOut { get; set; }
public string DayOfTheWeek { get; set; }
public int LocationId { get; set; }
public TimeSpan TotalTime { get; set; }
public byte StatusId { get; set; }
public TimeSpan BreakTime { get; set; }
}
然后在调用数据库后得到这样的结果 IEnumerable<Attendace>
:
var result = await _platformDB.Con.QueryAsync<Models.Attendance.Attendance>(query);
然后我创建了一个像这样的简单视图模型:
public class Time
{
public DateTime DateTimeUtcIn { get; set; }
public DateTime DateTimeUtcOut { get; set; }
}
public class AttendaceViewModel
{
public int UserId { get; set; }
public string FullName { get; set; }
public string Date { get; set; }
public string DayOfTheWeek { get; set; }
public List<Time> TimesInAndOut { get; set; }
public string Locations { get; set; }
public string TotalTime { get; set; } //need to calculate
public string Status { get; set; }
public string BreakTime { get; set; } //need to calculate
}
现在问题来了:我如何根据按 UserId 分组的结果创建 List<AttendaceViewModel>
并计算一天的 TotalTime(所有 dateTimeUtcIn + dateTimeUtcOut 的总和)和这一天的休息时间并填充此 List<Time> TimesInAndOut
在这里?
我真的不知道。
仅使用 LINQ 可能无法完成此操作。您应该能够遍历刚刚获取的结果中返回的项目,并在那里执行您的逻辑。
像这样实现一个函数,并在检索结果后调用它。如果您愿意,您甚至可以在此函数中处理数据库查询,然后只需调用该函数并取回您的列表。
private List<AttendanceViewModel> GetAttendanceViewModels((whatever type 'results' is goes here) {type} results)
{
var output = new List<AttendanceViewModel>();
foreach(result in results)
{
var totalTime = CalculateTotalTimeForOneDay(result);
var breakTime = CalculateBreakTime(result);
result.TotalTime = totalTime;
result.BreakTime = breakTime;
}
return output.GroupBy(u => u.UserId)
}
我想我知道你需要什么:
List<AttendaceViewModel> resultList = result
.GroupBy(a => (a.UserId, a.FullName, DateIn: a.DateTimeUtcIn.Date, a.DayOfTheWeek, a.LocationId, a.StatusId))
.Select(ag => new AttendaceViewModel
{
UserId = ag.Key.UserId,
FullName = ag.Key.FullName,
Date = ag.Key.DateIn.ToString(),
DayOfTheWeek = ag.Key.DayOfTheWeek,
Locations = ag.Key.LocationId.ToString(),
Status = ag.Key.StatusId.ToString(),
TotalTime = new TimeSpan(ag.Sum(a => (a.DateTimeUtcOut - a.DateTimeUtcIn).Ticks)).ToString(),
TimesInAndOut = ag.Select(a => new Time { DateTimeUtcIn = a.DateTimeUtcIn, DateTimeUtcOut = a.DateTimeUtcOut }).ToList(),
BreakTime = CalcBreaks(ag.Select(a => (a.DateTimeUtcIn, a.DateTimeUtcOut))).ToString()
})
.ToList();
对于 BreakTime
我使用了这个辅助方法:
private static TimeSpan CalcBreaks(IEnumerable<(DateTime inTime, DateTime outTime)> times)
{
if (!times.Skip(1).Any())
return TimeSpan.Zero;
TimeSpan totalBreakTime = TimeSpan.Zero;
TimeSpan lastLeaveTime = times.First().outTime.TimeOfDay;
foreach(var attendanceTime in times.OrderBy(at => at.inTime).ThenBy(at => at.outTime).Skip(1))
{
TimeSpan breakTime = attendanceTime.inTime.TimeOfDay - lastLeaveTime;
totalBreakTime += breakTime;
lastLeaveTime = attendanceTime.outTime.TimeOfDay;
}
return totalBreakTime;
}
我无法从通过 Dapper 从数据库中获取的对象列表创建一个特定的“数据集”。所以事情是关于公司的日常出勤,所以用户来了,点击,出去,点击,我们有一个 table 行,如下所示: sql table 所以我有一个像这样的模型 class:
public class Attendance
{
public int UserId { get; set; }
public string FullName { get; set; }
public DateTime DateTimeUtcIn { get; set; }
public DateTime DateTimeUtcOut { get; set; }
public string DayOfTheWeek { get; set; }
public int LocationId { get; set; }
public TimeSpan TotalTime { get; set; }
public byte StatusId { get; set; }
public TimeSpan BreakTime { get; set; }
}
然后在调用数据库后得到这样的结果 IEnumerable<Attendace>
:
var result = await _platformDB.Con.QueryAsync<Models.Attendance.Attendance>(query);
然后我创建了一个像这样的简单视图模型:
public class Time
{
public DateTime DateTimeUtcIn { get; set; }
public DateTime DateTimeUtcOut { get; set; }
}
public class AttendaceViewModel
{
public int UserId { get; set; }
public string FullName { get; set; }
public string Date { get; set; }
public string DayOfTheWeek { get; set; }
public List<Time> TimesInAndOut { get; set; }
public string Locations { get; set; }
public string TotalTime { get; set; } //need to calculate
public string Status { get; set; }
public string BreakTime { get; set; } //need to calculate
}
现在问题来了:我如何根据按 UserId 分组的结果创建 List<AttendaceViewModel>
并计算一天的 TotalTime(所有 dateTimeUtcIn + dateTimeUtcOut 的总和)和这一天的休息时间并填充此 List<Time> TimesInAndOut
在这里?
我真的不知道。
仅使用 LINQ 可能无法完成此操作。您应该能够遍历刚刚获取的结果中返回的项目,并在那里执行您的逻辑。
像这样实现一个函数,并在检索结果后调用它。如果您愿意,您甚至可以在此函数中处理数据库查询,然后只需调用该函数并取回您的列表。
private List<AttendanceViewModel> GetAttendanceViewModels((whatever type 'results' is goes here) {type} results)
{
var output = new List<AttendanceViewModel>();
foreach(result in results)
{
var totalTime = CalculateTotalTimeForOneDay(result);
var breakTime = CalculateBreakTime(result);
result.TotalTime = totalTime;
result.BreakTime = breakTime;
}
return output.GroupBy(u => u.UserId)
}
我想我知道你需要什么:
List<AttendaceViewModel> resultList = result
.GroupBy(a => (a.UserId, a.FullName, DateIn: a.DateTimeUtcIn.Date, a.DayOfTheWeek, a.LocationId, a.StatusId))
.Select(ag => new AttendaceViewModel
{
UserId = ag.Key.UserId,
FullName = ag.Key.FullName,
Date = ag.Key.DateIn.ToString(),
DayOfTheWeek = ag.Key.DayOfTheWeek,
Locations = ag.Key.LocationId.ToString(),
Status = ag.Key.StatusId.ToString(),
TotalTime = new TimeSpan(ag.Sum(a => (a.DateTimeUtcOut - a.DateTimeUtcIn).Ticks)).ToString(),
TimesInAndOut = ag.Select(a => new Time { DateTimeUtcIn = a.DateTimeUtcIn, DateTimeUtcOut = a.DateTimeUtcOut }).ToList(),
BreakTime = CalcBreaks(ag.Select(a => (a.DateTimeUtcIn, a.DateTimeUtcOut))).ToString()
})
.ToList();
对于 BreakTime
我使用了这个辅助方法:
private static TimeSpan CalcBreaks(IEnumerable<(DateTime inTime, DateTime outTime)> times)
{
if (!times.Skip(1).Any())
return TimeSpan.Zero;
TimeSpan totalBreakTime = TimeSpan.Zero;
TimeSpan lastLeaveTime = times.First().outTime.TimeOfDay;
foreach(var attendanceTime in times.OrderBy(at => at.inTime).ThenBy(at => at.outTime).Skip(1))
{
TimeSpan breakTime = attendanceTime.inTime.TimeOfDay - lastLeaveTime;
totalBreakTime += breakTime;
lastLeaveTime = attendanceTime.outTime.TimeOfDay;
}
return totalBreakTime;
}