使用 LINQ 创建特定数据集

发布于 2025-01-20 03:06:32 字数 1783 浏览 2 评论 0原文

我无法从通过 Dapper 从数据库获取的对象列表中创建一个特定的“数据集”。所以问题是关于公司的日常出勤情况,因此用户进来并单击,出去并单击,我们有一个像这样的表行: sql表 所以我有一个像这样的模型类:

    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

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 并计算一天的 TotalTime(所有 dateTimeUtcIn + 的总和) dateTimeUtcOut) 和当天的休息时间,并填充此 List

I have trouble with creating one specific "dataset" from list of objects which I get via Dapper from database. So the thing is about daily attendancies in company, so user comes and click and goes out and click and we have one table row like this:
sql table
So I have a model class like this:

    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; }
    }

and then after a call to the database I have result like this IEnumerable<Attendace>:

var result = await _platformDB.Con.QueryAsync<Models.Attendance.Attendance>(query);

then I created a simple viewmodel like this:

    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
     }

and here comes the QUESTION now: how can I create List<AttendaceViewModel> from my result grouped by UserId and calculate TotalTime for one day (sum of all dateTimeUtcIn + dateTimeUtcOut) and breaktime for this day and also populate this List<Time> TimesInAndOut in here?
I have really no idea.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独夜无伴 2025-01-27 03:06:32

我想我知道你需要什么:

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;
}

I think i know what you need:

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();

For the BreakTime i used this helper method:

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;
}
一城柳絮吹成雪 2025-01-27 03:06:32

仅使用 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)
}

You probably won't be able accomplish that with just LINQ. You should be able to loop over the items returned in the results that you just fetched, and do your logic there.

Implement a function like this, and call it after retrieving your results. You could even handle the database querying in this function too if you'd like, then just call the function and get back your list.

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)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文