在时间范围之间对获取项目进行分组

时间:2017-09-29 14:12:52

标签: 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
}

现在,我想将所有工作人员与他们的班次进行分组,然后使用ActionType 2或4获取所有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 = "..." }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

如果我理解你的问题,你不需要分组。相反,你需要扩展,为每个工人转移所采取的行动。下面的代码应指向正确的方向:

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