c# - 在时间范围内对获取项目进行分组

标签 c# entity-framework linq grouping

我有这个 EntityFramework DatabaseContext 给定:

class Worker
{
    int Id,
    string Name,
    ...
    ICollection<Shift> Shifts
}

class Shift
{
    int Id,
    DateTime ShiftStart
    DateTime ShiftEnd
    ...
    Worker Worker
}

class CustomerAction
{
    int Id,
    Worker Worker,
    DateTime ArrivalTime,
    int ActionType
    ...
    string Comment
}

现在我想将所有 Worker 及其轮类分组,然后获取 ActionType 为 2 或 4 的所有 CustomerActions。

有时 worker 不添加他们的类次,那么 worker 完成的所有其他 CustomerActions 应该列出空类次信息。

输出应该是这样的:

List = 
{
    new Item
    {
        WorkerId = 1, WorkerName = "Worker1" ...
        ShiftId = 1, ShiftStart = 10/1/2017 1:00:00 AM, ShiftEnd = 10/1/2017 5:00:00 AM ...

        // Sorted by ArrivalTime, only in between the ShiftStart / ShiftEnd Range, done by this Worker
        CustomerActions = 
        {
            new CustomerAction { ActionId = 1, ActionType = 4, ArrivalTime = 10/1/2017 1:00:00 AM, Comment = "My comment" }
            new CustomerAction { ActionId = 2, ActionType = 2, ArrivalTime = 10/1/2017 1:30:00 AM, Comment = "Some other comment" }
            new CustomerAction { ActionId = 3, ActionType = 4, ArrivalTime = 10/1/2017 2:00:00 AM, Comment = "No comment" }
        }
    }
    new Item
    {
        WorkerId = 2, WorkerName = "Worker2" ...
        ShiftId = null, ShiftStart = null, ShiftEnd = null ...

        // Sorted by ArrivalTime, done by this Worker, Without an Shift
        CustomerActions = 
        {
            new CustomerAction { ActionId = 4, ActionType = 4, ArrivalTime = 10/2/2017 1:00:00 AM, Comment = "..." }
            new CustomerAction { ActionId = 5, ActionType = 2, ArrivalTime = 10/3/2017 1:30:00 AM, Comment = "..." }
            new CustomerAction { ActionId = 6, ActionType = 4, ArrivalTime = 10/4/2017 2:00:00 AM, Comment = "..." }
        }
    }
}

最佳答案

如果我对您的问题的理解正确,则您不需要分组。相反,您需要扩展,因为每个 worker 都会转移所处理的操作。下面的代码应该为您指明正确的方向:

var registeredShifts = dbContext.Workers
    .SelectMany(w => w.Shifts.Select(s => new
    {
        WorkerId = w.Id,
        WorkerName = w.Name,
        ShiftId = s.Id,
        ShiftStart = s.ShiftStart,
        ShiftEnd = s.ShiftEnd,
        CustomerActions =  dbContext.CustomerActions
            .Where(a => a.Worker.Id == w.Id && 
                    a.ArrivalTime >= s.ShiftStart &&
                    a.ArrivalTime <= s.ShiftEnd &&
                    (a.ActionType == 2 || a.ActionType == 4))
            .ToList()
    }))

编辑:要在已注册类次之外的操作获得相同的结果,您必须使用分组。

var outsideShifts = dbContrxt.CustomerActions
    .Where(a => a.ActionType == 2 || a.ActionType == 4)
    .Where(a => a.Worker.Shifts.All(s => a.ArrivalTime < s.ShiftStart ||
                                         a.ArrivalTime > s.ShiftEnd))
    .GroupBy(a => new 
    { 
        WorkerId = a.Worker.Id,
        WorkerName = a.Worker.Name
    })
    .Select(g => new
    {
        WorkerId = g.Key.WorkerId,
        WorkerName = g.Key.WorkerName,
        ShiftId = null,
        ShiftStart = null,
        ShiftEnd = null,
        CustomerActions = g.ToList()
    });

最后得到需要的数据,Union()上面的结果:

var result = registeredShifts.Union(outsideShifts);
return result.ToArray();

关于c# - 在时间范围内对获取项目进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46490682/

相关文章:

c# - 如何在列表中列出具有不为空的字段的元素编号?

c# - 从元组列表中删除重复项

c# - LINQ 表达式树 Any() inside Where()

c# - 从搜索满足条件的 xy 点列表中获得 3 个结果 c#

c# - LINQ to Entities 无法识别该方法并且无法将此方法转换为存储表达式

c# - 了解 PagedList mvc 和 Entity Framework (慢查询)

c# - 如何为 Like 创建 System.Linq.Expressions.Expression?

c# - 为 C# 包装 native DLL

c# - 使用泛型在类的值类型之间进行转换

c# - 为什么 Entity Framework 中忽略 uint 枚举