Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq 在对象图中深层过滤集合_Linq_Entity Framework_Linq To Entities_Asp.net Web Api - Fatal编程技术网

Linq 在对象图中深层过滤集合

Linq 在对象图中深层过滤集合,linq,entity-framework,linq-to-entities,asp.net-web-api,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构建一个图表。该图表仅显示start

以下是我试图做的: 我的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);
AmSerialChart AmSerialChart=
(AmSerialChart)db.AmSerialCharts
.查找(id)
.图表
.选择(g=>g.Measure)
.SelectMany(m=>m.MeasureData)

.Where(md=>md.Timestamp>=startDate&&md.Timestamp有时单行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);
  }
}
var fullChart=charts.Where(c=>c.Id==Id.Single();
var result=new AmSerialChart()
{
Id=fullChart.Id,
Name=fullChart.Name,
Description=完整图表。Description,
FirstTimestamp=fullChart.FirstTimestamp,
LastTimestamp=fullChart.LastTimestamp,
图=新列表()
};
foreach(fullChart.Graphs中的var图)
{
var度量=图。度量;
var newMeasure=新度量()
{
Id=measure.Id,
//复制其余的数据
MeasureData=新列表()
};
foreach(测量中的var测量数据。测量数据)
{
if(measureData.Timestamp>=startDate&&measureData.Timestamp 0)
{
var newGraph=newGraph()
{
Id=graph.Id,
//复制其余的数据
度量=新度量
};
result.Graphs.Add(newGraph);
}
}
过滤测量数据并返回AmSerialChart对象

您最好使用
Any()

var-measureData=charts.Where(c=>c.Id==Id
&&c.Graphs.Any(g=>g.Measure.MeasureData

任何(md=>md.Timestamp>=startDate&&md.Timestamp图形表的点是什么?@Justin-图形是一个图表对象。每个AmSerialChart可以有一个或多个图形。最后,我将向图形对象添加属性,例如线颜色、线厚度等。每个图形仅与一个度量值关联。但是,度量值可以是grap他看到了不止一个图形。感谢您提供的跳过测量对象的提示。但是,您的答案返回的是IEnumerable of MeasureData,而不是AmSerialChart。测试您的答案也让我意识到我不需要SelectMany运算符,因为它会在所有测量中展平所有测量数据。您是否希望一个
AmSerialChart
对象及其
Graph
对象和
MeasureData
被修剪为只包含在您的时间范围内的数据?如果
id
标识的
AmSerialChart
没有此类度量数据,您是否仍然希望
AmSerialChart
包含这些数据?这可能很难做到o向您提供一个已筛选到所需数据的对象。原因是源对象是一个包含完整数据的“完整”对象,您必须将所有对象复制到层次结构中,这样您就不会修改原始的“完整数据”版本。您不仅能够“选择”一个经过删减的版本,没有可能的负面影响。我理解你的方法(实际上我自己也是沿着同一条路径前进的),但复制对象层次结构似乎重复了大量代码。尽管这个答案返回了一个AmSerialChart对象(+1),它不会过滤掉startDate endDate范围之外的测量数据实体。如果使用
All()
而不是
Any()
(两次),您将选择一个
AmSerialChart
,其中所有图只在指定的时间间隔内具有测量数据。通常这是非常(非常)的严格的条件,但它可能对您的数据是正确的。当我使用
Any()
(两次)时,只要至少有一个时间戳在范围内,就会返回所有测量数据。当我使用
all()
(两次)时,如果至少有一个时间戳超出范围,则不会返回任何被测数据。这是有道理的,但我尝试返回时间戳在范围内的被测数据,并排除时间戳超出范围的被测数据。在我看来,我应该应用
Where()
运算符针对MeasureData集合,但我不确定如何在LINQ语句中执行该操作。您可以使用范围中的
MeasureData
启动查询,然后选择
Measure
Graph
AmSerialChart
,但我认为这将得到与
All
相同的结果。
var measureData = charts.Where(c => c.Id == id
     && c.Graphs.Any(g => g.Measure.MeasureData
    .Any(md => md.Timestamp >= startDate && md.Timestamp <= endDate)))
    .FirstOrDefault();