LINQ查询基于两个列表返回元素并基于多个属性处理结果

时间:2018-02-15 15:12:26

标签: c# entity-framework linq

我希望我能够妥善解释我的要求。我有一个传入的JSON请求,其中包含以下数据:

public class OptimalDateSlotInput
{

    public IEnumerable<LoadareaLocationsDTO> Locations { get; set; }
    public DateTime From { get; set; }
    public DateTime To { get; set; }


    public class LoadareaLocationsDTO
    {
        public string id { get; set; }
        public int bundles { get; set; }
    }
}

根据这些数据,我必须从我的数据库返回特定时间范围内的结果(时间段)(从和到),仅针对特定的位置列表,并且只有剩余容量的时间段&gt; =每个地点捆绑。这就是我创建的返回所需结果的内容:

    public IEnumerable<PlannedSlot> GetOptimalDateSlots(OptimalDateSlotInput input)
    {
        List<PlannedSlot> returnList = new List<PlannedSlot>();
        var loadAreaList = input.Locations.Select(d => d.id);
        List<int> bundlesList = input.Locations.Select(d => d.bundles).ToList();
        var filterQuery = _context.Slots.Where(d => d.From >= input.From && 
                                                        d.To <= input.To && 
                                                        loadAreaList.Contains(d.LoadArea))
                                                        .ToList();                 

        foreach (var item in filterQuery)
        {
            foreach (var bundle in bundlesList)
            {
                if (item.RemainingCapacity >= bundle)
                    returnList.Add(item);
            }
        }

        return returnList.Distinct();
    }

我只设法分两步执行此操作,并且我不太喜欢我被迫使用的Foreach循环,以便根据每个Locations包属性过滤结果,该属性必须是&lt; = each条目剩余容量。

现在,在我得到这些结果之后,我需要根据我的需要对它们进行调整,这些需求只会同时返回所有input.Locations.id From可用区域的插槽。

我是按照以下方式做到这一点的,我不确定它有多精确:

    public IHttpActionResult GetOptimalDateSlot(OptimalDateSlotInput input)
    {
        var availableSlots = _repo.GetOptimalDateSlots(input);
        var areas = input.Locations.Select(d => d.id);
        var slotsToReturn = Mapper.Map<IEnumerable<PlannedSlotDto>>(availableSlots);

        var optimalSlots = slotsToReturn.GroupBy(d => d.From).Where(group => group.Count() == areas.Count());

        return Ok(optimalSlots);
    }

当我使用Count()方法时,我试图确保这些组的数量等于实际带来所需结果的input.Locations.id。但是,如果只返回(From)中所有ID的安全时间input.Locations.id可用的插槽,还有其他一些方法。我希望我能够正确解释这个问题。

1 个答案:

答案 0 :(得分:1)

您可以使用LINQ替换循环以找到可能的日期插槽(我更改了一些变量名称以使其更清晰):

public IEnumerable<PlannedSlot> GetOptimalDateSlots(OptimalDateSlotInput input) {
    var inputLoadAreas = new HashSet<string>(input.Locations.Select(d => d.id));
    var inputBundles = input.Locations.Select(d => d.bundles);
    var possibleSlots = _context.Slots.Where(slot => slot.From >= input.From && slot.To <= input.To &&
                                                  inputLoadAreas.Contains(slot.LoadArea))
                                       .Where(slot => inputBundles.Any(bundle => slot.RemainingCapacity > bundle));
    return possibleSlots;
}

然后,您可以找到包含所有输入载入区域的所有可能日期:

public IHttpActionResult GetOptimalDateSlot(OptimalDateSlotInput input) {
    var inputAreas = input.Locations.Select(d => d.id).ToList();
    var optimalSlots = GetOptimalDateSlots(input).GroupBy(slot => slot.From)
                                                 .Where(slotg => inputAreas.All(a => slotg.Any(slot => slot.LoadArea == a)));
    var slotsToReturn = Mapper.Map<IEnumerable<PlannedSlotDto>>(optimalSlots);

    return Ok(optimalSlots);
}