在对象图中深入过滤集合

时间:2013-06-05 17:48:28

标签: linq entity-framework linq-to-entities asp.net-web-api

以下是我要做的事情: 我的ASP.NET Web API接受来自客户端的图表“id”,“startTimestamp”和“endTimestamp”。我需要Web API只选择在startTimestamp和endTimestamp定义的时间戳范围内的“MeasureData”(参见附加的EF5概念模型图)。我的Web API将JSON AmSerialChart对象图返回给客户端。然后我解析JSON对象图并使用amCharts Javascript API构建图表。该图表仅显示startTimestamp和endTimestamp之间的数据。

我无法弄清楚如何在我的控制器中编写LINQ表达式,它将过滤MeasureData并返回带有过滤MeasureData的AmSerialChart对象。

这是一次失败的尝试:

AmSerialChart amserialchart =
(AmSerialChart)db.AmSerialCharts
.Find(id)
.Graphs
.Select(g => g.Measure)
.SelectMany(m => m.MeasureData)
.Where(md => md.Timestamp >= startDate && md.Timestamp <= endDate);

“db.AmSerialCharts.Find(id)”找到合适的图表实体,但我不确定如何浏览对象图的其余部分以进入MeasureData过滤器。

2 个答案:

答案 0 :(得分:1)

有时,单行LINQ不是问题的最佳解决方案。即使可能,可读性也常常会消失。有时,最好手动完成工作。

您的请求的问题在于您希望AmSerialChart对象的完整对象层次结构经过修剪以符合您的时间范围。问题是基本Select不会这样做。它将要生成一个新列表或新对象。

我认为您最好的解决方案是“复制”您的对象层次结构,而不是尝试LINQ它:

var fullChart = charts.Where(c => c.Id == id).Single();
var result = new AmSerialChart()
{
  Id = fullChart.Id,
  Name = fullChart.Name,
  Description = fullChart.Description,
  FirstTimestamp = fullChart.FirstTimestamp,
  LastTimestamp = fullChart.LastTimestamp,
  Graphs = new List<Graph>()
};

foreach (var graph in fullChart.Graphs)
{
  var measure = graph.Measure;

  var newMeasure = new Measure()
  {
    Id = measure.Id,
    // Copy the rest of data

    MeasureData = new List<MeasureData>()
  };

  foreach (var measureData in measure.MeasureData)
  {
    if (measureData.Timestamp >= startDate && measureData.Timestamp <= endDate)
    {
      var newMeasureData = new MeasureData()
      {
        Id = measureData.Id,
        // Copy the rest of data
      };
      newMeasure.MeasureData.Add(newMeasureData);
    }
  }

  if (newMeasure.MeasureData.Count() > 0)
  {
    var newGraph = new Graph()
    {
      Id = graph.Id,
      // Copy the rest of data

      Measure = newMeasure
    };
    result.Graphs.Add(newGraph);
  }
}

答案 1 :(得分:1)

  

过滤MeasureData并返回AmSerialChart对象

您最好使用Any()

var measureData = charts.Where(c => c.Id == id
     && c.Graphs.Any(g => g.Measure.MeasureData
    .Any(md => md.Timestamp >= startDate && md.Timestamp <= endDate)))
    .FirstOrDefault();

SingleOrDefault()如果预计不超过1个匹配。