以下是我要做的事情: 我的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过滤器。
答案 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个匹配。