title: LINQ - filtering, grouping and getting Min and Max value
body: <p>Let's say that I have an EF entity class that represents some value in time:</p>
  
  <pre><code>public class Point
  {
      public DateTime DT {get; set;}
      public decimal Value {get; set;}
  }
  </code></pre>
  
  <p>I have also a class that represents some time period:</p>
  
  <pre><code>public class Period
  {
      public DateTime Begin {get; set;}
      public DateTime End {get; set;}
  }
  </code></pre>
  
  <p>Then I have an array of <code>Period</code>'s that can contain some specific time slices, let's say that it looks like (<code>Period</code> objects are always in ascending order in the array):</p>
  
  <pre><code>var periodSlices = new Period [] 
  {
      new Period { Begin = new DateTime(2016, 10, 1), End = new DateTime(2016, 10, 15)},
      new Period { Begin = new DateTime(2016, 10, 16), End = new DateTime(2016, 10, 20)},
      new Period { Begin = new DateTime(2016, 10, 21), End = new DateTime(2016, 12, 30)}
  };
  </code></pre>
  
  <p>Now, using LINQ to SQL how to write a query which would filter out and group the <code>Point</code>'s with oldest(min) and latest(max) values within each of <code>periodSlices</code>, so in this example scenario a results should have a 3 groups with min and max points (if any of course).</p>
  
  <p>So what I need to have as a result is something like <code>IQueryable&lt;Period, IEnumerable&lt;Point&gt;&gt;</code>.</p>
  
  <p>Right now I am doing it this way, but the performance is not the greatest:</p>
  
  <pre><code>using (var context = new EfDbContext())
  {
      var periodBegin = periodSlices[0].Begin;
      var periodEnd = periodSlices[periodSlices.Length - 1].End;
  
       var dbPoints = context.Points.Where(p =&gt; p.DT &gt;= periodBegin &amp;&amp; p.DT &lt;= periodEnd).ToArray();
  
      foreach (var slice in periodSlices)
      {
          var points = dbPoints.Where(p =&gt; p.DT &gt;= slice.Begin &amp;&amp; p.DT &lt;= slice.End);
  
          if (points.Any())
          {
              var latestValue = points.MaxBy(u =&gt; u.DT).Value;
              var earliestValue = points.MinBy(u =&gt; u.DT).Value;
          }
      }   
  }
  </code></pre>
  
  <p>Performance is crucial (the faster the better as I need to filter out and group ~100k of points).</p>