我有一个Readings
的实体集合。
每个Reading
都链接到一个名为Meter
的实体。
(并且每个Meter
拥有多个读数)。
每个Reading
都有一个用于计量表ID(int)的字段和一个用于时间的字段。
下面是一些简化的代码来演示它:
public class Reading
{
int Id;
int meterId;
DateTime time;
}
public class Meter
{
int id;
ICollection<Readings> readings;
}
给定特定的时间段和
meterid
列表,什么是最有效的方式来获取每个仪表
在那个时间段的第一读和最后读?
我可以遍历所有仪表,并且每米都可以进行迭代
该期间的第一读和最后读,
但是我在徘徊,是否有一种更有效的方法来实现这一目标。
还有一个红利问题:同一个问题,但是要花费很多时间才能获取数据,
而不只是一个时期。
最佳答案
我不确定要如何获取这些数据,但可以将其投影为匿名类型:
var metersFirstAndLastReading = meters.Select(m => new
{
Meter = m,
FirstReading = m.readings.OrderBy(r => r.time).First(),
LastReading = m.readings.OrderBy(r => r.time).Last()
});
然后,您可以像这样读取结果列表(此示例仅作为示例):
foreach(var currentReading in metersFirstAndLastReading)
{
string printReadings = String.Format("Meter id {0}, First = {1}, Last = {2}",
currentReading.Meter.id.ToString(),
currentReading.FirstReading.time.ToString(),
currentReading.LastReading.time.ToString());
// Do something...
}
另一个选择是在Meter中创建属性,该属性动态返回第一个和最后一个读数:
public class Meter
{
public int id;
public List<Reading> readings;
public Reading FirstReading
{
get
{
return readings.OrderBy(r => r.time).First();
}
}
public Reading LastReading
{
get
{
return readings.OrderBy(r => r.time).Last();
}
}
}
编辑:我对这个问题有点误解了。
这是确定仪表(包括)的日期范围的首末读数的实现(假设
meterIdList
是ID的ICollection<int>
和begin
,而end
是指定的日期范围)var metersFirstAndLastReading = meters
.Where(m => meterIdList.Contains(m.id))
.Select(m => new
{
Meter = m,
FirstReading = m.readings
.Where(r => r.time >= begin && r.time <= end)
.OrderBy(r => r.time)
.FirstOrDefault(),
LastReading = m.readings
.Where(r => r.time >= begin && r.time <= end)
.OrderByDescending(r => r.time)
.FirstOrDefault()
});
您现在将无法使用属性(因为您需要提供参数),因此方法可以很好地替代:
public class Meter
{
public int id;
public List<Reading> readings;
public Reading GetFirstReading(DateTime begin, DateTime end)
{
var filteredReadings = readings.Where(r => r.time >= begin && r.time <= end);
if(!HasReadings(begin, end))
{
throw new ArgumentOutOfRangeException("No readings available during this period");
}
return filteredReadings.OrderBy(r => r.time).First();
}
public Reading GetLastReading(DateTime begin, DateTime end)
{
var filteredReadings = readings.Where(r => r.time >= begin && r.time <= end);
if(!HasReadings(begin, end))
{
throw new ArgumentOutOfRangeException("No readings available during this period");
}
return filteredReadings.OrderBy(r => r.time).Last();
}
public bool HasReadings(DateTime begin, DateTime end)
{
return readings.Any(r => r.time >= begin && r.time <= end);
}
}